diff --git a/README.md b/README.md
index 68a3d84..b479260 100644
--- a/README.md
+++ b/README.md
@@ -7,12 +7,13 @@
Contains source and object code built from:
- SQLite3 from [sqlite.org](http://sqlite.org/) (public domain)
- [liteglue / Android-sqlite-native-driver](https://github.com/liteglue/Android-sqlite-native-driver) (Unlicense, public domain)
-- [liteglue / Android-sqlite-connector](https://github.com/liteglue/Android-sqlite-connector) (Unlicense, public domain)
+- [brodybits / Android-sqlite-ext-native-driver (sqlite-storage-native-driver branch)](https://github.com/brodybits/Android-sqlite-ext-native-driver/tree/sqlite-storage-native-driver) (Unlicense, public domain)
This project provides the following dependencies needed to build [litehelpers / Cordova-sqlite-storage](https://github.com/litehelpers/Cordova-sqlite-storage):
-- `sqlite3.h`, `sqlite3.c` - SQLite `3.15.2` amalgamation needed to build iOS and Windows versions
-- `libs` - [liteglue / Android-sqlite-connector](https://github.com/liteglue/Android-sqlite-connector) and [liteglue / Android-sqlite-native-driver](https://github.com/liteglue/Android-sqlite-native-driver) JAR libraries built with SQLite `3.15.2` amalgamation, with the following flags:
+- `sqlite3.h`, `sqlite3.c` - SQLite `3.22.0` amalgamation needed to build iOS and Windows versions
+- `libs` - [liteglue / Android-sqlite-connector](https://github.com/liteglue/Android-sqlite-connector) and [brodybits / Android-sqlite-ext-native-driver (sqlite-storage-native-driver branch)](https://github.com/brodybits/Android-sqlite-ext-native-driver/tree/sqlite-storage-native-driver) JAR libraries built with SQLite `3.22.0` amalgamation, with the following flags:
- `-DSQLITE_THREADSAFE=1`
+ - `-DSQLITE_DEFAULT_SYNCHRONOUS=3`
- `-DSQLITE_DEFAULT_MEMSTATUS=0`
- `-DSQLITE_OMIT_DECLTYPE`
- `-DSQLITE_OMIT_DEPRECATED`
diff --git a/libs/sqlite-native-driver.jar b/libs/sqlite-native-driver.jar
index 53f2fcb..b1850ad 100644
Binary files a/libs/sqlite-native-driver.jar and b/libs/sqlite-native-driver.jar differ
diff --git a/package.json b/package.json
index 80c0734..065b91c 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "cordova-sqlite-storage-dependencies",
- "version": "1.1.0",
+ "version": "1.2.0",
"description": "Cordova sqlite storage dependencies",
"main": "404.js",
"scripts": {
diff --git a/sqlite3.c b/sqlite3.c
index aaab200..73c69ef 100644
--- a/sqlite3.c
+++ b/sqlite3.c
@@ -1,6 +1,6 @@
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
-** version 3.15.2. By combining all the individual C code files into this
+** version 3.22.0. By combining all the individual C code files into this
** single large file, the entire code can be compiled as a single translation
** unit. This allows many compilers to do optimizations that would not be
** possible if the files were compiled separately. Performance improvements
@@ -22,6 +22,761 @@
#ifndef SQLITE_PRIVATE
# define SQLITE_PRIVATE static
#endif
+/************** Begin file ctime.c *******************************************/
+/*
+** 2010 February 23
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file implements routines used to report what compile-time options
+** SQLite was built with.
+*/
+
+#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
+
+/*
+** Include the configuration header output by 'configure' if we're using the
+** autoconf-based build
+*/
+#if defined(_HAVE_SQLITE_CONFIG_H) && !defined(SQLITECONFIG_H)
+#include "config.h"
+#define SQLITECONFIG_H 1
+#endif
+
+/* These macros are provided to "stringify" the value of the define
+** for those options in which the value is meaningful. */
+#define CTIMEOPT_VAL_(opt) #opt
+#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
+
+/*
+** An array of names of all compile-time options. This array should
+** be sorted A-Z.
+**
+** This array looks large, but in a typical installation actually uses
+** only a handful of compile-time options, so most times this array is usually
+** rather short and uses little memory space.
+*/
+static const char * const sqlite3azCompileOpt[] = {
+
+/*
+** BEGIN CODE GENERATED BY tool/mkctime.tcl
+*/
+#if SQLITE_32BIT_ROWID
+ "32BIT_ROWID",
+#endif
+#if SQLITE_4_BYTE_ALIGNED_MALLOC
+ "4_BYTE_ALIGNED_MALLOC",
+#endif
+#if SQLITE_64BIT_STATS
+ "64BIT_STATS",
+#endif
+#if SQLITE_ALLOW_COVERING_INDEX_SCAN
+ "ALLOW_COVERING_INDEX_SCAN",
+#endif
+#if SQLITE_ALLOW_URI_AUTHORITY
+ "ALLOW_URI_AUTHORITY",
+#endif
+#ifdef SQLITE_BITMASK_TYPE
+ "BITMASK_TYPE=" CTIMEOPT_VAL(SQLITE_BITMASK_TYPE),
+#endif
+#if SQLITE_BUG_COMPATIBLE_20160819
+ "BUG_COMPATIBLE_20160819",
+#endif
+#if SQLITE_CASE_SENSITIVE_LIKE
+ "CASE_SENSITIVE_LIKE",
+#endif
+#if SQLITE_CHECK_PAGES
+ "CHECK_PAGES",
+#endif
+#if defined(__clang__) && defined(__clang_major__)
+ "COMPILER=clang-" CTIMEOPT_VAL(__clang_major__) "."
+ CTIMEOPT_VAL(__clang_minor__) "."
+ CTIMEOPT_VAL(__clang_patchlevel__),
+#elif defined(_MSC_VER)
+ "COMPILER=msvc-" CTIMEOPT_VAL(_MSC_VER),
+#elif defined(__GNUC__) && defined(__VERSION__)
+ "COMPILER=gcc-" __VERSION__,
+#endif
+#if SQLITE_COVERAGE_TEST
+ "COVERAGE_TEST",
+#endif
+#if SQLITE_DEBUG
+ "DEBUG",
+#endif
+#if SQLITE_DEFAULT_AUTOMATIC_INDEX
+ "DEFAULT_AUTOMATIC_INDEX",
+#endif
+#if SQLITE_DEFAULT_AUTOVACUUM
+ "DEFAULT_AUTOVACUUM",
+#endif
+#ifdef SQLITE_DEFAULT_CACHE_SIZE
+ "DEFAULT_CACHE_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_CACHE_SIZE),
+#endif
+#if SQLITE_DEFAULT_CKPTFULLFSYNC
+ "DEFAULT_CKPTFULLFSYNC",
+#endif
+#ifdef SQLITE_DEFAULT_FILE_FORMAT
+ "DEFAULT_FILE_FORMAT=" CTIMEOPT_VAL(SQLITE_DEFAULT_FILE_FORMAT),
+#endif
+#ifdef SQLITE_DEFAULT_FILE_PERMISSIONS
+ "DEFAULT_FILE_PERMISSIONS=" CTIMEOPT_VAL(SQLITE_DEFAULT_FILE_PERMISSIONS),
+#endif
+#if SQLITE_DEFAULT_FOREIGN_KEYS
+ "DEFAULT_FOREIGN_KEYS",
+#endif
+#ifdef SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT
+ "DEFAULT_JOURNAL_SIZE_LIMIT=" CTIMEOPT_VAL(SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT),
+#endif
+#ifdef SQLITE_DEFAULT_LOCKING_MODE
+ "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE),
+#endif
+#ifdef SQLITE_DEFAULT_LOOKASIDE
+ "DEFAULT_LOOKASIDE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOOKASIDE),
+#endif
+#if SQLITE_DEFAULT_MEMSTATUS
+ "DEFAULT_MEMSTATUS",
+#endif
+#ifdef SQLITE_DEFAULT_MMAP_SIZE
+ "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE),
+#endif
+#ifdef SQLITE_DEFAULT_PAGE_SIZE
+ "DEFAULT_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_PAGE_SIZE),
+#endif
+#ifdef SQLITE_DEFAULT_PCACHE_INITSZ
+ "DEFAULT_PCACHE_INITSZ=" CTIMEOPT_VAL(SQLITE_DEFAULT_PCACHE_INITSZ),
+#endif
+#ifdef SQLITE_DEFAULT_PROXYDIR_PERMISSIONS
+ "DEFAULT_PROXYDIR_PERMISSIONS=" CTIMEOPT_VAL(SQLITE_DEFAULT_PROXYDIR_PERMISSIONS),
+#endif
+#if SQLITE_DEFAULT_RECURSIVE_TRIGGERS
+ "DEFAULT_RECURSIVE_TRIGGERS",
+#endif
+#ifdef SQLITE_DEFAULT_ROWEST
+ "DEFAULT_ROWEST=" CTIMEOPT_VAL(SQLITE_DEFAULT_ROWEST),
+#endif
+#ifdef SQLITE_DEFAULT_SECTOR_SIZE
+ "DEFAULT_SECTOR_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_SECTOR_SIZE),
+#endif
+#ifdef SQLITE_DEFAULT_SYNCHRONOUS
+ "DEFAULT_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_SYNCHRONOUS),
+#endif
+#ifdef SQLITE_DEFAULT_WAL_AUTOCHECKPOINT
+ "DEFAULT_WAL_AUTOCHECKPOINT=" CTIMEOPT_VAL(SQLITE_DEFAULT_WAL_AUTOCHECKPOINT),
+#endif
+#ifdef SQLITE_DEFAULT_WAL_SYNCHRONOUS
+ "DEFAULT_WAL_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_WAL_SYNCHRONOUS),
+#endif
+#ifdef SQLITE_DEFAULT_WORKER_THREADS
+ "DEFAULT_WORKER_THREADS=" CTIMEOPT_VAL(SQLITE_DEFAULT_WORKER_THREADS),
+#endif
+#if SQLITE_DIRECT_OVERFLOW_READ
+ "DIRECT_OVERFLOW_READ",
+#endif
+#if SQLITE_DISABLE_DIRSYNC
+ "DISABLE_DIRSYNC",
+#endif
+#if SQLITE_DISABLE_FTS3_UNICODE
+ "DISABLE_FTS3_UNICODE",
+#endif
+#if SQLITE_DISABLE_FTS4_DEFERRED
+ "DISABLE_FTS4_DEFERRED",
+#endif
+#if SQLITE_DISABLE_INTRINSIC
+ "DISABLE_INTRINSIC",
+#endif
+#if SQLITE_DISABLE_LFS
+ "DISABLE_LFS",
+#endif
+#if SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
+ "DISABLE_PAGECACHE_OVERFLOW_STATS",
+#endif
+#if SQLITE_DISABLE_SKIPAHEAD_DISTINCT
+ "DISABLE_SKIPAHEAD_DISTINCT",
+#endif
+#ifdef SQLITE_ENABLE_8_3_NAMES
+ "ENABLE_8_3_NAMES=" CTIMEOPT_VAL(SQLITE_ENABLE_8_3_NAMES),
+#endif
+#if SQLITE_ENABLE_API_ARMOR
+ "ENABLE_API_ARMOR",
+#endif
+#if SQLITE_ENABLE_ATOMIC_WRITE
+ "ENABLE_ATOMIC_WRITE",
+#endif
+#if SQLITE_ENABLE_BATCH_ATOMIC_WRITE
+ "ENABLE_BATCH_ATOMIC_WRITE",
+#endif
+#if SQLITE_ENABLE_CEROD
+ "ENABLE_CEROD",
+#endif
+#if SQLITE_ENABLE_COLUMN_METADATA
+ "ENABLE_COLUMN_METADATA",
+#endif
+#if SQLITE_ENABLE_COLUMN_USED_MASK
+ "ENABLE_COLUMN_USED_MASK",
+#endif
+#if SQLITE_ENABLE_COSTMULT
+ "ENABLE_COSTMULT",
+#endif
+#if SQLITE_ENABLE_CURSOR_HINTS
+ "ENABLE_CURSOR_HINTS",
+#endif
+#if SQLITE_ENABLE_DBSTAT_VTAB
+ "ENABLE_DBSTAT_VTAB",
+#endif
+#if SQLITE_ENABLE_EXPENSIVE_ASSERT
+ "ENABLE_EXPENSIVE_ASSERT",
+#endif
+#if SQLITE_ENABLE_FTS1
+ "ENABLE_FTS1",
+#endif
+#if SQLITE_ENABLE_FTS2
+ "ENABLE_FTS2",
+#endif
+#if SQLITE_ENABLE_FTS3
+ "ENABLE_FTS3",
+#endif
+#if SQLITE_ENABLE_FTS3_PARENTHESIS
+ "ENABLE_FTS3_PARENTHESIS",
+#endif
+#if SQLITE_ENABLE_FTS3_TOKENIZER
+ "ENABLE_FTS3_TOKENIZER",
+#endif
+#if SQLITE_ENABLE_FTS4
+ "ENABLE_FTS4",
+#endif
+#if SQLITE_ENABLE_FTS5
+ "ENABLE_FTS5",
+#endif
+#if SQLITE_ENABLE_HIDDEN_COLUMNS
+ "ENABLE_HIDDEN_COLUMNS",
+#endif
+#if SQLITE_ENABLE_ICU
+ "ENABLE_ICU",
+#endif
+#if SQLITE_ENABLE_IOTRACE
+ "ENABLE_IOTRACE",
+#endif
+#if SQLITE_ENABLE_JSON1
+ "ENABLE_JSON1",
+#endif
+#if SQLITE_ENABLE_LOAD_EXTENSION
+ "ENABLE_LOAD_EXTENSION",
+#endif
+#ifdef SQLITE_ENABLE_LOCKING_STYLE
+ "ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE),
+#endif
+#if SQLITE_ENABLE_MEMORY_MANAGEMENT
+ "ENABLE_MEMORY_MANAGEMENT",
+#endif
+#if SQLITE_ENABLE_MEMSYS3
+ "ENABLE_MEMSYS3",
+#endif
+#if SQLITE_ENABLE_MEMSYS5
+ "ENABLE_MEMSYS5",
+#endif
+#if SQLITE_ENABLE_MULTIPLEX
+ "ENABLE_MULTIPLEX",
+#endif
+#if SQLITE_ENABLE_NULL_TRIM
+ "ENABLE_NULL_TRIM",
+#endif
+#if SQLITE_ENABLE_OVERSIZE_CELL_CHECK
+ "ENABLE_OVERSIZE_CELL_CHECK",
+#endif
+#if SQLITE_ENABLE_PREUPDATE_HOOK
+ "ENABLE_PREUPDATE_HOOK",
+#endif
+#if SQLITE_ENABLE_QPSG
+ "ENABLE_QPSG",
+#endif
+#if SQLITE_ENABLE_RBU
+ "ENABLE_RBU",
+#endif
+#if SQLITE_ENABLE_RTREE
+ "ENABLE_RTREE",
+#endif
+#if SQLITE_ENABLE_SELECTTRACE
+ "ENABLE_SELECTTRACE",
+#endif
+#if SQLITE_ENABLE_SESSION
+ "ENABLE_SESSION",
+#endif
+#if SQLITE_ENABLE_SNAPSHOT
+ "ENABLE_SNAPSHOT",
+#endif
+#if SQLITE_ENABLE_SQLLOG
+ "ENABLE_SQLLOG",
+#endif
+#if defined(SQLITE_ENABLE_STAT4)
+ "ENABLE_STAT4",
+#elif defined(SQLITE_ENABLE_STAT3)
+ "ENABLE_STAT3",
+#endif
+#if SQLITE_ENABLE_STMTVTAB
+ "ENABLE_STMTVTAB",
+#endif
+#if SQLITE_ENABLE_STMT_SCANSTATUS
+ "ENABLE_STMT_SCANSTATUS",
+#endif
+#if SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
+ "ENABLE_UNKNOWN_SQL_FUNCTION",
+#endif
+#if SQLITE_ENABLE_UNLOCK_NOTIFY
+ "ENABLE_UNLOCK_NOTIFY",
+#endif
+#if SQLITE_ENABLE_UPDATE_DELETE_LIMIT
+ "ENABLE_UPDATE_DELETE_LIMIT",
+#endif
+#if SQLITE_ENABLE_URI_00_ERROR
+ "ENABLE_URI_00_ERROR",
+#endif
+#if SQLITE_ENABLE_VFSTRACE
+ "ENABLE_VFSTRACE",
+#endif
+#if SQLITE_ENABLE_WHERETRACE
+ "ENABLE_WHERETRACE",
+#endif
+#if SQLITE_ENABLE_ZIPVFS
+ "ENABLE_ZIPVFS",
+#endif
+#if SQLITE_EXPLAIN_ESTIMATED_ROWS
+ "EXPLAIN_ESTIMATED_ROWS",
+#endif
+#if SQLITE_EXTRA_IFNULLROW
+ "EXTRA_IFNULLROW",
+#endif
+#ifdef SQLITE_EXTRA_INIT
+ "EXTRA_INIT=" CTIMEOPT_VAL(SQLITE_EXTRA_INIT),
+#endif
+#ifdef SQLITE_EXTRA_SHUTDOWN
+ "EXTRA_SHUTDOWN=" CTIMEOPT_VAL(SQLITE_EXTRA_SHUTDOWN),
+#endif
+#ifdef SQLITE_FTS3_MAX_EXPR_DEPTH
+ "FTS3_MAX_EXPR_DEPTH=" CTIMEOPT_VAL(SQLITE_FTS3_MAX_EXPR_DEPTH),
+#endif
+#if SQLITE_FTS5_ENABLE_TEST_MI
+ "FTS5_ENABLE_TEST_MI",
+#endif
+#if SQLITE_FTS5_NO_WITHOUT_ROWID
+ "FTS5_NO_WITHOUT_ROWID",
+#endif
+#if SQLITE_HAS_CODEC
+ "HAS_CODEC",
+#endif
+#if HAVE_ISNAN || SQLITE_HAVE_ISNAN
+ "HAVE_ISNAN",
+#endif
+#if SQLITE_HOMEGROWN_RECURSIVE_MUTEX
+ "HOMEGROWN_RECURSIVE_MUTEX",
+#endif
+#if SQLITE_IGNORE_AFP_LOCK_ERRORS
+ "IGNORE_AFP_LOCK_ERRORS",
+#endif
+#if SQLITE_IGNORE_FLOCK_LOCK_ERRORS
+ "IGNORE_FLOCK_LOCK_ERRORS",
+#endif
+#if SQLITE_INLINE_MEMCPY
+ "INLINE_MEMCPY",
+#endif
+#if SQLITE_INT64_TYPE
+ "INT64_TYPE",
+#endif
+#ifdef SQLITE_INTEGRITY_CHECK_ERROR_MAX
+ "INTEGRITY_CHECK_ERROR_MAX=" CTIMEOPT_VAL(SQLITE_INTEGRITY_CHECK_ERROR_MAX),
+#endif
+#if SQLITE_LIKE_DOESNT_MATCH_BLOBS
+ "LIKE_DOESNT_MATCH_BLOBS",
+#endif
+#if SQLITE_LOCK_TRACE
+ "LOCK_TRACE",
+#endif
+#if SQLITE_LOG_CACHE_SPILL
+ "LOG_CACHE_SPILL",
+#endif
+#ifdef SQLITE_MALLOC_SOFT_LIMIT
+ "MALLOC_SOFT_LIMIT=" CTIMEOPT_VAL(SQLITE_MALLOC_SOFT_LIMIT),
+#endif
+#ifdef SQLITE_MAX_ATTACHED
+ "MAX_ATTACHED=" CTIMEOPT_VAL(SQLITE_MAX_ATTACHED),
+#endif
+#ifdef SQLITE_MAX_COLUMN
+ "MAX_COLUMN=" CTIMEOPT_VAL(SQLITE_MAX_COLUMN),
+#endif
+#ifdef SQLITE_MAX_COMPOUND_SELECT
+ "MAX_COMPOUND_SELECT=" CTIMEOPT_VAL(SQLITE_MAX_COMPOUND_SELECT),
+#endif
+#ifdef SQLITE_MAX_DEFAULT_PAGE_SIZE
+ "MAX_DEFAULT_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_DEFAULT_PAGE_SIZE),
+#endif
+#ifdef SQLITE_MAX_EXPR_DEPTH
+ "MAX_EXPR_DEPTH=" CTIMEOPT_VAL(SQLITE_MAX_EXPR_DEPTH),
+#endif
+#ifdef SQLITE_MAX_FUNCTION_ARG
+ "MAX_FUNCTION_ARG=" CTIMEOPT_VAL(SQLITE_MAX_FUNCTION_ARG),
+#endif
+#ifdef SQLITE_MAX_LENGTH
+ "MAX_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_LENGTH),
+#endif
+#ifdef SQLITE_MAX_LIKE_PATTERN_LENGTH
+ "MAX_LIKE_PATTERN_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_LIKE_PATTERN_LENGTH),
+#endif
+#ifdef SQLITE_MAX_MEMORY
+ "MAX_MEMORY=" CTIMEOPT_VAL(SQLITE_MAX_MEMORY),
+#endif
+#ifdef SQLITE_MAX_MMAP_SIZE
+ "MAX_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE),
+#endif
+#ifdef SQLITE_MAX_MMAP_SIZE_
+ "MAX_MMAP_SIZE_=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE_),
+#endif
+#ifdef SQLITE_MAX_PAGE_COUNT
+ "MAX_PAGE_COUNT=" CTIMEOPT_VAL(SQLITE_MAX_PAGE_COUNT),
+#endif
+#ifdef SQLITE_MAX_PAGE_SIZE
+ "MAX_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_PAGE_SIZE),
+#endif
+#ifdef SQLITE_MAX_SCHEMA_RETRY
+ "MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY),
+#endif
+#ifdef SQLITE_MAX_SQL_LENGTH
+ "MAX_SQL_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_SQL_LENGTH),
+#endif
+#ifdef SQLITE_MAX_TRIGGER_DEPTH
+ "MAX_TRIGGER_DEPTH=" CTIMEOPT_VAL(SQLITE_MAX_TRIGGER_DEPTH),
+#endif
+#ifdef SQLITE_MAX_VARIABLE_NUMBER
+ "MAX_VARIABLE_NUMBER=" CTIMEOPT_VAL(SQLITE_MAX_VARIABLE_NUMBER),
+#endif
+#ifdef SQLITE_MAX_VDBE_OP
+ "MAX_VDBE_OP=" CTIMEOPT_VAL(SQLITE_MAX_VDBE_OP),
+#endif
+#ifdef SQLITE_MAX_WORKER_THREADS
+ "MAX_WORKER_THREADS=" CTIMEOPT_VAL(SQLITE_MAX_WORKER_THREADS),
+#endif
+#if SQLITE_MEMDEBUG
+ "MEMDEBUG",
+#endif
+#if SQLITE_MIXED_ENDIAN_64BIT_FLOAT
+ "MIXED_ENDIAN_64BIT_FLOAT",
+#endif
+#if SQLITE_MMAP_READWRITE
+ "MMAP_READWRITE",
+#endif
+#if SQLITE_MUTEX_NOOP
+ "MUTEX_NOOP",
+#endif
+#if SQLITE_MUTEX_NREF
+ "MUTEX_NREF",
+#endif
+#if SQLITE_MUTEX_OMIT
+ "MUTEX_OMIT",
+#endif
+#if SQLITE_MUTEX_PTHREADS
+ "MUTEX_PTHREADS",
+#endif
+#if SQLITE_MUTEX_W32
+ "MUTEX_W32",
+#endif
+#if SQLITE_NEED_ERR_NAME
+ "NEED_ERR_NAME",
+#endif
+#if SQLITE_NOINLINE
+ "NOINLINE",
+#endif
+#if SQLITE_NO_SYNC
+ "NO_SYNC",
+#endif
+#if SQLITE_OMIT_ALTERTABLE
+ "OMIT_ALTERTABLE",
+#endif
+#if SQLITE_OMIT_ANALYZE
+ "OMIT_ANALYZE",
+#endif
+#if SQLITE_OMIT_ATTACH
+ "OMIT_ATTACH",
+#endif
+#if SQLITE_OMIT_AUTHORIZATION
+ "OMIT_AUTHORIZATION",
+#endif
+#if SQLITE_OMIT_AUTOINCREMENT
+ "OMIT_AUTOINCREMENT",
+#endif
+#if SQLITE_OMIT_AUTOINIT
+ "OMIT_AUTOINIT",
+#endif
+#if SQLITE_OMIT_AUTOMATIC_INDEX
+ "OMIT_AUTOMATIC_INDEX",
+#endif
+#if SQLITE_OMIT_AUTORESET
+ "OMIT_AUTORESET",
+#endif
+#if SQLITE_OMIT_AUTOVACUUM
+ "OMIT_AUTOVACUUM",
+#endif
+#if SQLITE_OMIT_BETWEEN_OPTIMIZATION
+ "OMIT_BETWEEN_OPTIMIZATION",
+#endif
+#if SQLITE_OMIT_BLOB_LITERAL
+ "OMIT_BLOB_LITERAL",
+#endif
+#if SQLITE_OMIT_BTREECOUNT
+ "OMIT_BTREECOUNT",
+#endif
+#if SQLITE_OMIT_CAST
+ "OMIT_CAST",
+#endif
+#if SQLITE_OMIT_CHECK
+ "OMIT_CHECK",
+#endif
+#if SQLITE_OMIT_COMPLETE
+ "OMIT_COMPLETE",
+#endif
+#if SQLITE_OMIT_COMPOUND_SELECT
+ "OMIT_COMPOUND_SELECT",
+#endif
+#if SQLITE_OMIT_CONFLICT_CLAUSE
+ "OMIT_CONFLICT_CLAUSE",
+#endif
+#if SQLITE_OMIT_CTE
+ "OMIT_CTE",
+#endif
+#if SQLITE_OMIT_DATETIME_FUNCS
+ "OMIT_DATETIME_FUNCS",
+#endif
+#if SQLITE_OMIT_DECLTYPE
+ "OMIT_DECLTYPE",
+#endif
+#if SQLITE_OMIT_DEPRECATED
+ "OMIT_DEPRECATED",
+#endif
+#if SQLITE_OMIT_DISKIO
+ "OMIT_DISKIO",
+#endif
+#if SQLITE_OMIT_EXPLAIN
+ "OMIT_EXPLAIN",
+#endif
+#if SQLITE_OMIT_FLAG_PRAGMAS
+ "OMIT_FLAG_PRAGMAS",
+#endif
+#if SQLITE_OMIT_FLOATING_POINT
+ "OMIT_FLOATING_POINT",
+#endif
+#if SQLITE_OMIT_FOREIGN_KEY
+ "OMIT_FOREIGN_KEY",
+#endif
+#if SQLITE_OMIT_GET_TABLE
+ "OMIT_GET_TABLE",
+#endif
+#if SQLITE_OMIT_HEX_INTEGER
+ "OMIT_HEX_INTEGER",
+#endif
+#if SQLITE_OMIT_INCRBLOB
+ "OMIT_INCRBLOB",
+#endif
+#if SQLITE_OMIT_INTEGRITY_CHECK
+ "OMIT_INTEGRITY_CHECK",
+#endif
+#if SQLITE_OMIT_LIKE_OPTIMIZATION
+ "OMIT_LIKE_OPTIMIZATION",
+#endif
+#if SQLITE_OMIT_LOAD_EXTENSION
+ "OMIT_LOAD_EXTENSION",
+#endif
+#if SQLITE_OMIT_LOCALTIME
+ "OMIT_LOCALTIME",
+#endif
+#if SQLITE_OMIT_LOOKASIDE
+ "OMIT_LOOKASIDE",
+#endif
+#if SQLITE_OMIT_MEMORYDB
+ "OMIT_MEMORYDB",
+#endif
+#if SQLITE_OMIT_OR_OPTIMIZATION
+ "OMIT_OR_OPTIMIZATION",
+#endif
+#if SQLITE_OMIT_PAGER_PRAGMAS
+ "OMIT_PAGER_PRAGMAS",
+#endif
+#if SQLITE_OMIT_PARSER_TRACE
+ "OMIT_PARSER_TRACE",
+#endif
+#if SQLITE_OMIT_POPEN
+ "OMIT_POPEN",
+#endif
+#if SQLITE_OMIT_PRAGMA
+ "OMIT_PRAGMA",
+#endif
+#if SQLITE_OMIT_PROGRESS_CALLBACK
+ "OMIT_PROGRESS_CALLBACK",
+#endif
+#if SQLITE_OMIT_QUICKBALANCE
+ "OMIT_QUICKBALANCE",
+#endif
+#if SQLITE_OMIT_REINDEX
+ "OMIT_REINDEX",
+#endif
+#if SQLITE_OMIT_SCHEMA_PRAGMAS
+ "OMIT_SCHEMA_PRAGMAS",
+#endif
+#if SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
+ "OMIT_SCHEMA_VERSION_PRAGMAS",
+#endif
+#if SQLITE_OMIT_SHARED_CACHE
+ "OMIT_SHARED_CACHE",
+#endif
+#if SQLITE_OMIT_SHUTDOWN_DIRECTORIES
+ "OMIT_SHUTDOWN_DIRECTORIES",
+#endif
+#if SQLITE_OMIT_SUBQUERY
+ "OMIT_SUBQUERY",
+#endif
+#if SQLITE_OMIT_TCL_VARIABLE
+ "OMIT_TCL_VARIABLE",
+#endif
+#if SQLITE_OMIT_TEMPDB
+ "OMIT_TEMPDB",
+#endif
+#if SQLITE_OMIT_TEST_CONTROL
+ "OMIT_TEST_CONTROL",
+#endif
+#if SQLITE_OMIT_TRACE
+ "OMIT_TRACE",
+#endif
+#if SQLITE_OMIT_TRIGGER
+ "OMIT_TRIGGER",
+#endif
+#if SQLITE_OMIT_TRUNCATE_OPTIMIZATION
+ "OMIT_TRUNCATE_OPTIMIZATION",
+#endif
+#if SQLITE_OMIT_UTF16
+ "OMIT_UTF16",
+#endif
+#if SQLITE_OMIT_VACUUM
+ "OMIT_VACUUM",
+#endif
+#if SQLITE_OMIT_VIEW
+ "OMIT_VIEW",
+#endif
+#if SQLITE_OMIT_VIRTUALTABLE
+ "OMIT_VIRTUALTABLE",
+#endif
+#if SQLITE_OMIT_WAL
+ "OMIT_WAL",
+#endif
+#if SQLITE_OMIT_WSD
+ "OMIT_WSD",
+#endif
+#if SQLITE_OMIT_XFER_OPT
+ "OMIT_XFER_OPT",
+#endif
+#if SQLITE_PCACHE_SEPARATE_HEADER
+ "PCACHE_SEPARATE_HEADER",
+#endif
+#if SQLITE_PERFORMANCE_TRACE
+ "PERFORMANCE_TRACE",
+#endif
+#if SQLITE_POWERSAFE_OVERWRITE
+ "POWERSAFE_OVERWRITE",
+#endif
+#if SQLITE_PREFER_PROXY_LOCKING
+ "PREFER_PROXY_LOCKING",
+#endif
+#if SQLITE_PROXY_DEBUG
+ "PROXY_DEBUG",
+#endif
+#if SQLITE_REVERSE_UNORDERED_SELECTS
+ "REVERSE_UNORDERED_SELECTS",
+#endif
+#if SQLITE_RTREE_INT_ONLY
+ "RTREE_INT_ONLY",
+#endif
+#if SQLITE_SECURE_DELETE
+ "SECURE_DELETE",
+#endif
+#if SQLITE_SMALL_STACK
+ "SMALL_STACK",
+#endif
+#ifdef SQLITE_SORTER_PMASZ
+ "SORTER_PMASZ=" CTIMEOPT_VAL(SQLITE_SORTER_PMASZ),
+#endif
+#if SQLITE_SOUNDEX
+ "SOUNDEX",
+#endif
+#ifdef SQLITE_STAT4_SAMPLES
+ "STAT4_SAMPLES=" CTIMEOPT_VAL(SQLITE_STAT4_SAMPLES),
+#endif
+#ifdef SQLITE_STMTJRNL_SPILL
+ "STMTJRNL_SPILL=" CTIMEOPT_VAL(SQLITE_STMTJRNL_SPILL),
+#endif
+#if SQLITE_SUBSTR_COMPATIBILITY
+ "SUBSTR_COMPATIBILITY",
+#endif
+#if SQLITE_SYSTEM_MALLOC
+ "SYSTEM_MALLOC",
+#endif
+#if SQLITE_TCL
+ "TCL",
+#endif
+#ifdef SQLITE_TEMP_STORE
+ "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE),
+#endif
+#if SQLITE_TEST
+ "TEST",
+#endif
+#if defined(SQLITE_THREADSAFE)
+ "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE),
+#elif defined(THREADSAFE)
+ "THREADSAFE=" CTIMEOPT_VAL(THREADSAFE),
+#else
+ "THREADSAFE=1",
+#endif
+#if SQLITE_UNLINK_AFTER_CLOSE
+ "UNLINK_AFTER_CLOSE",
+#endif
+#if SQLITE_UNTESTABLE
+ "UNTESTABLE",
+#endif
+#if SQLITE_USER_AUTHENTICATION
+ "USER_AUTHENTICATION",
+#endif
+#if SQLITE_USE_ALLOCA
+ "USE_ALLOCA",
+#endif
+#if SQLITE_USE_FCNTL_TRACE
+ "USE_FCNTL_TRACE",
+#endif
+#if SQLITE_USE_URI
+ "USE_URI",
+#endif
+#if SQLITE_VDBE_COVERAGE
+ "VDBE_COVERAGE",
+#endif
+#if SQLITE_WIN32_MALLOC
+ "WIN32_MALLOC",
+#endif
+#if SQLITE_ZERO_MALLOC
+ "ZERO_MALLOC",
+#endif
+/*
+** END CODE GENERATED BY tool/mkctime.tcl
+*/
+};
+
+SQLITE_PRIVATE const char **sqlite3CompileOptions(int *pnOpt){
+ *pnOpt = sizeof(sqlite3azCompileOpt) / sizeof(sqlite3azCompileOpt[0]);
+ return (const char**)sqlite3azCompileOpt;
+}
+
+#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
+
+/************** End of ctime.c ***********************************************/
/************** Begin file sqliteInt.h ***************************************/
/*
** 2001 September 15
@@ -75,14 +830,6 @@
# define SQLITE_TCLAPI
#endif
-/*
-** Make sure that rand_s() is available on Windows systems with MSVC 2005
-** or higher.
-*/
-#if defined(_MSC_VER) && _MSC_VER>=1400
-# define _CRT_RAND_S
-#endif
-
/*
** Include the header file used to customize the compiler options for MSVC.
** This should be done first so that it can successfully prevent spurious
@@ -204,12 +951,29 @@
# define _LARGEFILE_SOURCE 1
#endif
-/* What version of GCC is being used. 0 means GCC is not being used */
-#ifdef __GNUC__
+/* The GCC_VERSION and MSVC_VERSION macros are used to
+** conditionally include optimizations for each of these compilers. A
+** value of 0 means that compiler is not being used. The
+** SQLITE_DISABLE_INTRINSIC macro means do not use any compiler-specific
+** optimizations, and hence set all compiler macros to 0
+**
+** There was once also a CLANG_VERSION macro. However, we learn that the
+** version numbers in clang are for "marketing" only and are inconsistent
+** and unreliable. Fortunately, all versions of clang also recognize the
+** gcc version numbers and have reasonable settings for gcc version numbers,
+** so the GCC_VERSION macro will be set to a correct non-zero value even
+** when compiling with clang.
+*/
+#if defined(__GNUC__) && !defined(SQLITE_DISABLE_INTRINSIC)
# define GCC_VERSION (__GNUC__*1000000+__GNUC_MINOR__*1000+__GNUC_PATCHLEVEL__)
#else
# define GCC_VERSION 0
#endif
+#if defined(_MSC_VER) && !defined(SQLITE_DISABLE_INTRINSIC)
+# define MSVC_VERSION _MSC_VER
+#else
+# define MSVC_VERSION 0
+#endif
/* Needed for various definitions... */
#if defined(__GNUC__) && !defined(_GNU_SOURCE)
@@ -259,7 +1023,7 @@
/************** Include sqlite3.h in the middle of sqliteInt.h ***************/
/************** Begin file sqlite3.h *****************************************/
/*
-** 2001 September 15
+** 2001-09-15
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
@@ -374,20 +1138,22 @@ extern "C" {
** system. ^The SQLITE_SOURCE_ID macro evaluates to
** a string which identifies a particular check-in of SQLite
** within its configuration management system. ^The SQLITE_SOURCE_ID
-** string contains the date and time of the check-in (UTC) and an SHA1
-** hash of the entire source tree.
+** string contains the date and time of the check-in (UTC) and a SHA1
+** or SHA3-256 hash of the entire source tree. If the source code has
+** been edited in any way since it was last checked in, then the last
+** four hexadecimal digits of the hash may be modified.
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-#define SQLITE_VERSION "3.15.2"
-#define SQLITE_VERSION_NUMBER 3015002
-#define SQLITE_SOURCE_ID "2016-11-28 19:13:37 bbd85d235f7037c6a033a9690534391ffeacecc8"
+#define SQLITE_VERSION "3.22.0"
+#define SQLITE_VERSION_NUMBER 3022000
+#define SQLITE_SOURCE_ID "2018-01-22 18:45:57 0c55d179733b46d8d0ba4d88e01a25e10677046ee3da1d5b1581e86726f2171d"
/*
** CAPI3REF: Run-Time Library Version Numbers
-** KEYWORDS: sqlite3_version, sqlite3_sourceid
+** KEYWORDS: sqlite3_version sqlite3_sourceid
**
** These interfaces provide the same information as the [SQLITE_VERSION],
** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros
@@ -399,7 +1165,7 @@ extern "C" {
**
**
** assert( sqlite3_libversion_number()==SQLITE_VERSION_NUMBER );
-** assert( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)==0 );
+** assert( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,80)==0 );
** assert( strcmp(sqlite3_libversion(),SQLITE_VERSION)==0 );
**
)^
**
@@ -409,9 +1175,11 @@ extern "C" {
** function is provided for use in DLLs since DLL users usually do not have
** direct access to string constants within the DLL. ^The
** sqlite3_libversion_number() function returns an integer equal to
-** [SQLITE_VERSION_NUMBER]. ^The sqlite3_sourceid() function returns
+** [SQLITE_VERSION_NUMBER]. ^(The sqlite3_sourceid() function returns
** a pointer to a string constant whose value is the same as the
-** [SQLITE_SOURCE_ID] C preprocessor macro.
+** [SQLITE_SOURCE_ID] C preprocessor macro. Except if SQLite is built
+** using an edited copy of [the amalgamation], then the last four characters
+** of the hash might be different from [SQLITE_SOURCE_ID].)^
**
** See also: [sqlite_version()] and [sqlite_source_id()].
*/
@@ -519,7 +1287,11 @@ typedef struct sqlite3 sqlite3;
*/
#ifdef SQLITE_INT64_TYPE
typedef SQLITE_INT64_TYPE sqlite_int64;
- typedef unsigned SQLITE_INT64_TYPE sqlite_uint64;
+# ifdef SQLITE_UINT64_TYPE
+ typedef SQLITE_UINT64_TYPE sqlite_uint64;
+# else
+ typedef unsigned SQLITE_INT64_TYPE sqlite_uint64;
+# endif
#elif defined(_MSC_VER) || defined(__BORLANDC__)
typedef __int64 sqlite_int64;
typedef unsigned __int64 sqlite_uint64;
@@ -673,7 +1445,7 @@ SQLITE_API int sqlite3_exec(
*/
#define SQLITE_OK 0 /* Successful result */
/* beginning-of-error-codes */
-#define SQLITE_ERROR 1 /* SQL error or missing database */
+#define SQLITE_ERROR 1 /* Generic error */
#define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */
#define SQLITE_PERM 3 /* Access permission denied */
#define SQLITE_ABORT 4 /* Callback routine requested an abort */
@@ -688,7 +1460,7 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_FULL 13 /* Insertion failed because database is full */
#define SQLITE_CANTOPEN 14 /* Unable to open the database file */
#define SQLITE_PROTOCOL 15 /* Database lock protocol error */
-#define SQLITE_EMPTY 16 /* Database is empty */
+#define SQLITE_EMPTY 16 /* Internal use only */
#define SQLITE_SCHEMA 17 /* The database schema changed */
#define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */
#define SQLITE_CONSTRAINT 19 /* Abort due to constraint violation */
@@ -696,7 +1468,7 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_MISUSE 21 /* Library used incorrectly */
#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */
#define SQLITE_AUTH 23 /* Authorization denied */
-#define SQLITE_FORMAT 24 /* Auxiliary database format error */
+#define SQLITE_FORMAT 24 /* Not used */
#define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */
#define SQLITE_NOTADB 26 /* File opened that is not a database file */
#define SQLITE_NOTICE 27 /* Notifications from sqlite3_log() */
@@ -722,6 +1494,8 @@ SQLITE_API int sqlite3_exec(
** the most recent error can be obtained using
** [sqlite3_extended_errcode()].
*/
+#define SQLITE_ERROR_MISSING_COLLSEQ (SQLITE_ERROR | (1<<8))
+#define SQLITE_ERROR_RETRY (SQLITE_ERROR | (2<<8))
#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8))
#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8))
#define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8))
@@ -750,6 +1524,9 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_IOERR_CONVPATH (SQLITE_IOERR | (26<<8))
#define SQLITE_IOERR_VNODE (SQLITE_IOERR | (27<<8))
#define SQLITE_IOERR_AUTH (SQLITE_IOERR | (28<<8))
+#define SQLITE_IOERR_BEGIN_ATOMIC (SQLITE_IOERR | (29<<8))
+#define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8))
+#define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8))
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
#define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8))
@@ -762,6 +1539,8 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
#define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8))
#define SQLITE_READONLY_DBMOVED (SQLITE_READONLY | (4<<8))
+#define SQLITE_READONLY_CANTINIT (SQLITE_READONLY | (5<<8))
+#define SQLITE_READONLY_DIRECTORY (SQLITE_READONLY | (6<<8))
#define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8))
#define SQLITE_CONSTRAINT_CHECK (SQLITE_CONSTRAINT | (1<<8))
#define SQLITE_CONSTRAINT_COMMITHOOK (SQLITE_CONSTRAINT | (2<<8))
@@ -832,10 +1611,15 @@ SQLITE_API int sqlite3_exec(
** file that were written at the application level might have changed
** and that adjacent bytes, even bytes within the same sector are
** guaranteed to be unchanged. The SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN
-** flag indicate that a file cannot be deleted when open. The
+** flag indicates that a file cannot be deleted when open. The
** SQLITE_IOCAP_IMMUTABLE flag indicates that the file is on
** read-only media and cannot be changed even by processes with
** elevated privileges.
+**
+** The SQLITE_IOCAP_BATCH_ATOMIC property means that the underlying
+** filesystem supports doing multiple write operations atomically when those
+** write operations are bracketed by [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] and
+** [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE].
*/
#define SQLITE_IOCAP_ATOMIC 0x00000001
#define SQLITE_IOCAP_ATOMIC512 0x00000002
@@ -851,6 +1635,7 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 0x00000800
#define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000
#define SQLITE_IOCAP_IMMUTABLE 0x00002000
+#define SQLITE_IOCAP_BATCH_ATOMIC 0x00004000
/*
** CAPI3REF: File Locking Levels
@@ -982,6 +1767,10 @@ struct sqlite3_file {
** [SQLITE_IOCAP_ATOMIC64K]
** [SQLITE_IOCAP_SAFE_APPEND]
** [SQLITE_IOCAP_SEQUENTIAL]
+** [SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN]
+** [SQLITE_IOCAP_POWERSAFE_OVERWRITE]
+** [SQLITE_IOCAP_IMMUTABLE]
+** [SQLITE_IOCAP_BATCH_ATOMIC]
**
**
** The SQLITE_IOCAP_ATOMIC property means that all writes of
@@ -1110,7 +1899,7 @@ struct sqlite3_io_methods {
** opcode allows these two values (10 retries and 25 milliseconds of delay)
** to be adjusted. The values are changed for all database connections
** within the same process. The argument is a pointer to an array of two
-** integers where the first integer i the new retry count and the second
+** integers where the first integer is the new retry count and the second
** integer is the delay. If either integer is negative, then the setting
** is not changed but instead the prior value of that setting is written
** into the array entry, allowing the current retry settings to be
@@ -1265,6 +2054,40 @@ struct sqlite3_io_methods {
** The [SQLITE_FCNTL_RBU] opcode is implemented by the special VFS used by
** the RBU extension only. All other VFS should return SQLITE_NOTFOUND for
** this opcode.
+**
+** [[SQLITE_FCNTL_BEGIN_ATOMIC_WRITE]]
+** If the [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] opcode returns SQLITE_OK, then
+** the file descriptor is placed in "batch write mode", which
+** means all subsequent write operations will be deferred and done
+** atomically at the next [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE]. Systems
+** that do not support batch atomic writes will return SQLITE_NOTFOUND.
+** ^Following a successful SQLITE_FCNTL_BEGIN_ATOMIC_WRITE and prior to
+** the closing [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE] or
+** [SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE], SQLite will make
+** no VFS interface calls on the same [sqlite3_file] file descriptor
+** except for calls to the xWrite method and the xFileControl method
+** with [SQLITE_FCNTL_SIZE_HINT].
+**
+** [[SQLITE_FCNTL_COMMIT_ATOMIC_WRITE]]
+** The [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE] opcode causes all write
+** operations since the previous successful call to
+** [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] to be performed atomically.
+** This file control returns [SQLITE_OK] if and only if the writes were
+** all performed successfully and have been committed to persistent storage.
+** ^Regardless of whether or not it is successful, this file control takes
+** the file descriptor out of batch write mode so that all subsequent
+** write operations are independent.
+** ^SQLite will never invoke SQLITE_FCNTL_COMMIT_ATOMIC_WRITE without
+** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE].
+**
+** [[SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE]]
+** The [SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE] opcode causes all write
+** operations since the previous successful call to
+** [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] to be rolled back.
+** ^This file control takes the file descriptor out of batch write mode
+** so that all subsequent write operations are independent.
+** ^SQLite will never invoke SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE without
+** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE].
**
*/
#define SQLITE_FCNTL_LOCKSTATE 1
@@ -1295,6 +2118,10 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_VFS_POINTER 27
#define SQLITE_FCNTL_JOURNAL_POINTER 28
#define SQLITE_FCNTL_WIN32_GET_HANDLE 29
+#define SQLITE_FCNTL_PDB 30
+#define SQLITE_FCNTL_BEGIN_ATOMIC_WRITE 31
+#define SQLITE_FCNTL_COMMIT_ATOMIC_WRITE 32
+#define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE 33
/* deprecated names */
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
@@ -1332,12 +2159,18 @@ typedef struct sqlite3_api_routines sqlite3_api_routines;
** in the name of the object stands for "virtual file system". See
** the [VFS | VFS documentation] for further information.
**
-** The value of the iVersion field is initially 1 but may be larger in
-** future versions of SQLite. Additional fields may be appended to this
-** object when the iVersion value is increased. Note that the structure
-** of the sqlite3_vfs object changes in the transaction between
-** SQLite version 3.5.9 and 3.6.0 and yet the iVersion field was not
-** modified.
+** The VFS interface is sometimes extended by adding new methods onto
+** the end. Each time such an extension occurs, the iVersion field
+** is incremented. The iVersion value started out as 1 in
+** SQLite [version 3.5.0] on [dateof:3.5.0], then increased to 2
+** with SQLite [version 3.7.0] on [dateof:3.7.0], and then increased
+** to 3 with SQLite [version 3.7.6] on [dateof:3.7.6]. Additional fields
+** may be appended to the sqlite3_vfs object and the iVersion value
+** may increase again in future versions of SQLite.
+** Note that the structure
+** of the sqlite3_vfs object changes in the transition from
+** SQLite [version 3.5.9] to [version 3.6.0] on [dateof:3.6.0]
+** and yet the iVersion field was not modified.
**
** The szOsFile field is the size of the subclassed [sqlite3_file]
** structure used by this VFS. mxPathname is the maximum length of
@@ -1865,6 +2698,16 @@ struct sqlite3_mem_methods {
** routines with a wrapper that simulations memory allocation failure or
** tracks memory usage, for example.
**
+** [[SQLITE_CONFIG_SMALL_MALLOC]] SQLITE_CONFIG_SMALL_MALLOC
+** ^The SQLITE_CONFIG_SMALL_MALLOC option takes single argument of
+** type int, interpreted as a boolean, which if true provides a hint to
+** SQLite that it should avoid large memory allocations if possible.
+** SQLite will run faster if it is free to make large memory allocations,
+** but some application might prefer to run slower in exchange for
+** guarantees about memory fragmentation that are possible if large
+** allocations are avoided. This hint is normally off.
+**
+**
** [[SQLITE_CONFIG_MEMSTATUS]] SQLITE_CONFIG_MEMSTATUS
** ^The SQLITE_CONFIG_MEMSTATUS option takes single argument of type int,
** interpreted as a boolean, which enables or disables the collection of
@@ -1882,25 +2725,7 @@ struct sqlite3_mem_methods {
**
**
** [[SQLITE_CONFIG_SCRATCH]] SQLITE_CONFIG_SCRATCH
-** ^The SQLITE_CONFIG_SCRATCH option specifies a static memory buffer
-** that SQLite can use for scratch memory. ^(There are three arguments
-** to SQLITE_CONFIG_SCRATCH: A pointer an 8-byte
-** aligned memory buffer from which the scratch allocations will be
-** drawn, the size of each scratch allocation (sz),
-** and the maximum number of scratch allocations (N).)^
-** The first argument must be a pointer to an 8-byte aligned buffer
-** of at least sz*N bytes of memory.
-** ^SQLite will not use more than one scratch buffers per thread.
-** ^SQLite will never request a scratch buffer that is more than 6
-** times the database page size.
-** ^If SQLite needs needs additional
-** scratch memory beyond what is provided by this configuration option, then
-** [sqlite3_malloc()] will be used to obtain the memory needed.
-** ^When the application provides any amount of scratch memory using
-** SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary large
-** [sqlite3_malloc|heap allocations].
-** This can help [Robson proof|prevent memory allocation failures] due to heap
-** fragmentation in low-memory embedded systems.
+**
The SQLITE_CONFIG_SCRATCH option is no longer used.
**
**
** [[SQLITE_CONFIG_PAGECACHE]] SQLITE_CONFIG_PAGECACHE
@@ -1936,8 +2761,7 @@ struct sqlite3_mem_methods {
** [[SQLITE_CONFIG_HEAP]] SQLITE_CONFIG_HEAP
** ^The SQLITE_CONFIG_HEAP option specifies a static memory buffer
** that SQLite will use for all of its dynamic memory allocation needs
-** beyond those provided for by [SQLITE_CONFIG_SCRATCH] and
-** [SQLITE_CONFIG_PAGECACHE].
+** beyond those provided for by [SQLITE_CONFIG_PAGECACHE].
** ^The SQLITE_CONFIG_HEAP option is only available if SQLite is compiled
** with either [SQLITE_ENABLE_MEMSYS3] or [SQLITE_ENABLE_MEMSYS5] and returns
** [SQLITE_ERROR] if invoked otherwise.
@@ -2130,7 +2954,7 @@ struct sqlite3_mem_methods {
#define SQLITE_CONFIG_SERIALIZED 3 /* nil */
#define SQLITE_CONFIG_MALLOC 4 /* sqlite3_mem_methods* */
#define SQLITE_CONFIG_GETMALLOC 5 /* sqlite3_mem_methods* */
-#define SQLITE_CONFIG_SCRATCH 6 /* void*, int sz, int N */
+#define SQLITE_CONFIG_SCRATCH 6 /* No longer used */
#define SQLITE_CONFIG_PAGECACHE 7 /* void*, int sz, int N */
#define SQLITE_CONFIG_HEAP 8 /* void*, int nByte, int min */
#define SQLITE_CONFIG_MEMSTATUS 9 /* boolean */
@@ -2151,6 +2975,7 @@ struct sqlite3_mem_methods {
#define SQLITE_CONFIG_PCACHE_HDRSZ 24 /* int *psz */
#define SQLITE_CONFIG_PMASZ 25 /* unsigned int szPma */
#define SQLITE_CONFIG_STMTJRNL_SPILL 26 /* int nByte */
+#define SQLITE_CONFIG_SMALL_MALLOC 27 /* boolean */
/*
** CAPI3REF: Database Connection Configuration Options
@@ -2247,6 +3072,37 @@ struct sqlite3_mem_methods {
** until after the database connection closes.
**
**
+** SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE
+** Usually, when a database in wal mode is closed or detached from a
+** database handle, SQLite checks if this will mean that there are now no
+** connections at all to the database. If so, it performs a checkpoint
+** operation before closing the connection. This option may be used to
+** override this behaviour. The first parameter passed to this operation
+** is an integer - non-zero to disable checkpoints-on-close, or zero (the
+** default) to enable them. The second parameter is a pointer to an integer
+** into which is written 0 or 1 to indicate whether checkpoints-on-close
+** have been disabled - 0 if they are not disabled, 1 if they are.
+**
+** SQLITE_DBCONFIG_ENABLE_QPSG
+** ^(The SQLITE_DBCONFIG_ENABLE_QPSG option activates or deactivates
+** the [query planner stability guarantee] (QPSG). When the QPSG is active,
+** a single SQL query statement will always use the same algorithm regardless
+** of values of [bound parameters].)^ The QPSG disables some query optimizations
+** that look at the values of bound parameters, which can make some queries
+** slower. But the QPSG has the advantage of more predictable behavior. With
+** the QPSG active, SQLite will always use the same query plan in the field as
+** was used during testing in the lab.
+**
+** SQLITE_DBCONFIG_TRIGGER_EQP
+** By default, the output of EXPLAIN QUERY PLAN commands does not
+** include output for any operations performed by trigger programs. This
+** option is used to set or clear (the default) a flag that governs this
+** behavior. The first parameter passed to this operation is an integer -
+** non-zero to enable output for trigger programs, or zero to disable it.
+** The second parameter is a pointer to an integer into which is written
+** 0 or 1 to indicate whether output-for-triggers has been disabled - 0 if
+** it is not disabled, 1 if it is.
+**
**
*/
#define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */
@@ -2255,7 +3111,10 @@ struct sqlite3_mem_methods {
#define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */
#define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */
#define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */
-
+#define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */
+#define SQLITE_DBCONFIG_ENABLE_QPSG 1007 /* int int* */
+#define SQLITE_DBCONFIG_TRIGGER_EQP 1008 /* int int* */
+#define SQLITE_DBCONFIG_MAX 1008 /* Largest DBCONFIG */
/*
** CAPI3REF: Enable Or Disable Extended Result Codes
@@ -2279,20 +3138,30 @@ SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff);
** the table has a column of type [INTEGER PRIMARY KEY] then that column
** is another alias for the rowid.
**
-** ^The sqlite3_last_insert_rowid(D) interface returns the [rowid] of the
-** most recent successful [INSERT] into a rowid table or [virtual table]
-** on database connection D.
-** ^Inserts into [WITHOUT ROWID] tables are not recorded.
-** ^If no successful [INSERT]s into rowid tables
-** have ever occurred on the database connection D,
-** then sqlite3_last_insert_rowid(D) returns zero.
-**
-** ^(If an [INSERT] occurs within a trigger or within a [virtual table]
-** method, then this routine will return the [rowid] of the inserted
-** row as long as the trigger or virtual table method is running.
-** But once the trigger or virtual table method ends, the value returned
-** by this routine reverts to what it was before the trigger or virtual
-** table method began.)^
+** ^The sqlite3_last_insert_rowid(D) interface usually returns the [rowid] of
+** the most recent successful [INSERT] into a rowid table or [virtual table]
+** on database connection D. ^Inserts into [WITHOUT ROWID] tables are not
+** recorded. ^If no successful [INSERT]s into rowid tables have ever occurred
+** on the database connection D, then sqlite3_last_insert_rowid(D) returns
+** zero.
+**
+** As well as being set automatically as rows are inserted into database
+** tables, the value returned by this function may be set explicitly by
+** [sqlite3_set_last_insert_rowid()]
+**
+** Some virtual table implementations may INSERT rows into rowid tables as
+** part of committing a transaction (e.g. to flush data accumulated in memory
+** to disk). In this case subsequent calls to this function return the rowid
+** associated with these internal INSERT operations, which leads to
+** unintuitive results. Virtual table implementations that do write to rowid
+** tables in this way can avoid this problem by restoring the original
+** rowid value using [sqlite3_set_last_insert_rowid()] before returning
+** control to the user.
+**
+** ^(If an [INSERT] occurs within a trigger then this routine will
+** return the [rowid] of the inserted row as long as the trigger is
+** running. Once the trigger program ends, the value returned
+** by this routine reverts to what it was before the trigger was fired.)^
**
** ^An [INSERT] that fails due to a constraint violation is not a
** successful [INSERT] and does not change the value returned by this
@@ -2319,6 +3188,16 @@ SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff);
*/
SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*);
+/*
+** CAPI3REF: Set the Last Insert Rowid value.
+** METHOD: sqlite3
+**
+** The sqlite3_set_last_insert_rowid(D, R) method allows the application to
+** set the value returned by calling sqlite3_last_insert_rowid(D) to R
+** without inserting a row into the database.
+*/
+SQLITE_API void sqlite3_set_last_insert_rowid(sqlite3*,sqlite3_int64);
+
/*
** CAPI3REF: Count The Number Of Rows Modified
** METHOD: sqlite3
@@ -2430,9 +3309,6 @@ SQLITE_API int sqlite3_total_changes(sqlite3*);
** ^A call to sqlite3_interrupt(D) that occurs when there are no running
** SQL statements is a no-op and has no effect on SQL statements
** that are started after the sqlite3_interrupt() call returns.
-**
-** If the database connection closes while [sqlite3_interrupt()]
-** is running then bad things will likely happen.
*/
SQLITE_API void sqlite3_interrupt(sqlite3*);
@@ -2895,12 +3771,14 @@ SQLITE_API void sqlite3_randomness(int N, void *P);
/*
** CAPI3REF: Compile-Time Authorization Callbacks
** METHOD: sqlite3
+** KEYWORDS: {authorizer callback}
**
** ^This routine registers an authorizer callback with a particular
** [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
+** [sqlite3_prepare_v3()], [sqlite3_prepare16()], [sqlite3_prepare16_v2()],
+** and [sqlite3_prepare16_v3()]. ^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
@@ -2922,8 +3800,10 @@ SQLITE_API void sqlite3_randomness(int N, void *P);
** parameter to the sqlite3_set_authorizer() interface. ^The second parameter
** to the callback is an integer [SQLITE_COPY | action code] that specifies
** the particular action 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.
+** to the callback are either NULL pointers or zero-terminated strings
+** that contain additional details about the action to be authorized.
+** Applications must always be prepared to encounter a NULL pointer in any
+** of the third through the sixth parameters of the authorization callback.
**
** ^If the action code is [SQLITE_READ]
** and the callback returns [SQLITE_IGNORE] then the
@@ -2932,6 +3812,10 @@ SQLITE_API void sqlite3_randomness(int N, void *P);
** 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.
+** ^When a table is referenced by a [SELECT] but no column values are
+** extracted from that table (for example in a query like
+** "SELECT count(*) FROM tab") then the [SQLITE_READ] authorizer callback
+** is invoked once for that table with a column name that is an empty string.
** ^If the action code is [SQLITE_DELETE] and the callback returns
** [SQLITE_IGNORE] then the [DELETE] operation proceeds but the
** [truncate optimization] is disabled and all rows are deleted individually.
@@ -3091,8 +3975,8 @@ SQLITE_API SQLITE_DEPRECATED void *sqlite3_profile(sqlite3*,
** KEYWORDS: SQLITE_TRACE
**
** These constants identify classes of events that can be monitored
-** using the [sqlite3_trace_v2()] tracing logic. The third argument
-** to [sqlite3_trace_v2()] is an OR-ed combination of one or more of
+** using the [sqlite3_trace_v2()] tracing logic. The M argument
+** to [sqlite3_trace_v2(D,M,X,P)] is an OR-ed combination of one or more of
** the following constants. ^The first argument to the trace callback
** is one of the following constants.
**
@@ -3301,10 +4185,10 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** ^If [URI filename] interpretation is enabled, and the filename argument
** begins with "file:", then the filename is interpreted as a URI. ^URI
** filename interpretation is enabled if the [SQLITE_OPEN_URI] flag is
-** set in the fourth argument to sqlite3_open_v2(), or if it has
+** set in the third argument to sqlite3_open_v2(), or if it has
** been enabled globally using the [SQLITE_CONFIG_URI] option with the
** [sqlite3_config()] method or by the [SQLITE_USE_URI] compile-time option.
-** As of SQLite version 3.7.7, URI filename interpretation is turned off
+** URI filename interpretation is turned off
** by default, but future releases of SQLite might enable URI filename
** interpretation by default. See "[URI filenames]" for additional
** information.
@@ -3643,9 +4527,9 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
**
** [[SQLITE_LIMIT_VDBE_OP]] ^(SQLITE_LIMIT_VDBE_OP
** The maximum number of instructions in a virtual machine program
-** used to implement an SQL statement. This limit is not currently
-** enforced, though that might be added in some future release of
-** SQLite.)^
+** used to implement an SQL statement. If [sqlite3_prepare_v2()] or
+** the equivalent tries to allocate space for more than this many opcodes
+** in a single prepared statement, an SQLITE_NOMEM error is returned.)^
**
** [[SQLITE_LIMIT_FUNCTION_ARG]] ^(SQLITE_LIMIT_FUNCTION_ARG
** The maximum number of arguments on a function.)^
@@ -3683,23 +4567,59 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
#define SQLITE_LIMIT_TRIGGER_DEPTH 10
#define SQLITE_LIMIT_WORKER_THREADS 11
+/*
+** CAPI3REF: Prepare Flags
+**
+** These constants define various flags that can be passed into
+** "prepFlags" parameter of the [sqlite3_prepare_v3()] and
+** [sqlite3_prepare16_v3()] interfaces.
+**
+** New flags may be added in future releases of SQLite.
+**
+**
+** [[SQLITE_PREPARE_PERSISTENT]] ^(- SQLITE_PREPARE_PERSISTENT
+** - The SQLITE_PREPARE_PERSISTENT flag is a hint to the query planner
+** that the prepared statement will be retained for a long time and
+** probably reused many times.)^ ^Without this flag, [sqlite3_prepare_v3()]
+** and [sqlite3_prepare16_v3()] assume that the prepared statement will
+** be used just once or at most a few times and then destroyed using
+** [sqlite3_finalize()] relatively soon. The current implementation acts
+** on this hint by avoiding the use of [lookaside memory] so as not to
+** deplete the limited store of lookaside memory. Future versions of
+** SQLite may act on this hint differently.
+**
+*/
+#define SQLITE_PREPARE_PERSISTENT 0x01
+
/*
** CAPI3REF: Compiling An SQL Statement
** KEYWORDS: {SQL statement compiler}
** METHOD: sqlite3
** CONSTRUCTOR: sqlite3_stmt
**
-** To execute an SQL query, it must first be compiled into a byte-code
-** program using one of these routines.
+** To execute an SQL statement, it must first be compiled into a byte-code
+** program using one of these routines. Or, in other words, these routines
+** are constructors for the [prepared statement] object.
+**
+** The preferred routine to use is [sqlite3_prepare_v2()]. The
+** [sqlite3_prepare()] interface is legacy and should be avoided.
+** [sqlite3_prepare_v3()] has an extra "prepFlags" option that is used
+** for special purposes.
+**
+** The use of the UTF-8 interfaces is preferred, as SQLite currently
+** does all parsing using UTF-8. The UTF-16 interfaces are provided
+** as a convenience. The UTF-16 interfaces work by converting the
+** input text into UTF-8, then invoking the corresponding UTF-8 interface.
**
** The first argument, "db", is a [database connection] obtained from a
** prior successful call to [sqlite3_open()], [sqlite3_open_v2()] or
** [sqlite3_open16()]. The database connection must not have been closed.
**
** The second argument, "zSql", is the statement to be compiled, encoded
-** as either UTF-8 or UTF-16. The sqlite3_prepare() and sqlite3_prepare_v2()
-** interfaces use UTF-8, and sqlite3_prepare16() and sqlite3_prepare16_v2()
-** use UTF-16.
+** as either UTF-8 or UTF-16. The sqlite3_prepare(), sqlite3_prepare_v2(),
+** and sqlite3_prepare_v3()
+** interfaces use UTF-8, and sqlite3_prepare16(), sqlite3_prepare16_v2(),
+** and sqlite3_prepare16_v3() use UTF-16.
**
** ^If the nByte argument is negative, then zSql is read up to the
** first zero terminator. ^If nByte is positive, then it is the
@@ -3726,10 +4646,11 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
** ^On success, the sqlite3_prepare() family of routines return [SQLITE_OK];
** otherwise an [error code] is returned.
**
-** The sqlite3_prepare_v2() and sqlite3_prepare16_v2() interfaces are
-** recommended for all new programs. The two older interfaces are retained
-** for backwards compatibility, but their use is discouraged.
-** ^In the "v2" interfaces, the prepared statement
+** The sqlite3_prepare_v2(), sqlite3_prepare_v3(), sqlite3_prepare16_v2(),
+** and sqlite3_prepare16_v3() interfaces are recommended for all new programs.
+** The older interfaces (sqlite3_prepare() and sqlite3_prepare16())
+** are retained for backwards compatibility, but their use is discouraged.
+** ^In the "vX" interfaces, the prepared statement
** that is returned (the [sqlite3_stmt] object) contains a copy of the
** original SQL text. This causes the [sqlite3_step()] interface to
** behave differently in three ways:
@@ -3762,6 +4683,12 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
** or [GLOB] operator or if the parameter is compared to an indexed column
** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled.
**
+**
+** ^sqlite3_prepare_v3() differs from sqlite3_prepare_v2() only in having
+** the extra prepFlags parameter, which is a bit array consisting of zero or
+** more of the [SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_*] flags. ^The
+** sqlite3_prepare_v2() interface works exactly the same as
+** sqlite3_prepare_v3() with a zero prepFlags parameter.
**
*/
SQLITE_API int sqlite3_prepare(
@@ -3778,6 +4705,14 @@ SQLITE_API int sqlite3_prepare_v2(
sqlite3_stmt **ppStmt, /* OUT: Statement handle */
const char **pzTail /* OUT: Pointer to unused portion of zSql */
);
+SQLITE_API int sqlite3_prepare_v3(
+ sqlite3 *db, /* Database handle */
+ const char *zSql, /* SQL statement, UTF-8 encoded */
+ int nByte, /* Maximum length of zSql in bytes. */
+ unsigned int prepFlags, /* Zero or more SQLITE_PREPARE_ flags */
+ sqlite3_stmt **ppStmt, /* OUT: Statement handle */
+ const char **pzTail /* OUT: Pointer to unused portion of zSql */
+);
SQLITE_API int sqlite3_prepare16(
sqlite3 *db, /* Database handle */
const void *zSql, /* SQL statement, UTF-16 encoded */
@@ -3792,6 +4727,14 @@ SQLITE_API int sqlite3_prepare16_v2(
sqlite3_stmt **ppStmt, /* OUT: Statement handle */
const void **pzTail /* OUT: Pointer to unused portion of zSql */
);
+SQLITE_API int sqlite3_prepare16_v3(
+ sqlite3 *db, /* Database handle */
+ const void *zSql, /* SQL statement, UTF-16 encoded */
+ int nByte, /* Maximum length of zSql in bytes. */
+ unsigned int prepFlags, /* Zero or more SQLITE_PREPARE_ flags */
+ sqlite3_stmt **ppStmt, /* OUT: Statement handle */
+ const void **pzTail /* OUT: Pointer to unused portion of zSql */
+);
/*
** CAPI3REF: Retrieving Statement SQL
@@ -3799,7 +4742,8 @@ SQLITE_API int sqlite3_prepare16_v2(
**
** ^The sqlite3_sql(P) interface returns a pointer to a copy of the UTF-8
** SQL text used to create [prepared statement] P if P was
-** created by either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()].
+** created by [sqlite3_prepare_v2()], [sqlite3_prepare_v3()],
+** [sqlite3_prepare16_v2()], or [sqlite3_prepare16_v3()].
** ^The sqlite3_expanded_sql(P) interface returns a pointer to a UTF-8
** string containing the SQL text of prepared statement P with
** [bound parameters] expanded.
@@ -3856,6 +4800,10 @@ SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt);
** sqlite3_stmt_readonly() to return true since, while those statements
** change the configuration of a database connection, they do not make
** changes to the content of the database files on disk.
+** ^The sqlite3_stmt_readonly() interface returns true for [BEGIN] since
+** [BEGIN] merely sets internal flags, but the [BEGIN|BEGIN IMMEDIATE] and
+** [BEGIN|BEGIN EXCLUSIVE] commands do touch the database and so
+** sqlite3_stmt_readonly() returns false for those commands.
*/
SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
@@ -3914,12 +4862,13 @@ SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt*);
** 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()].
+** Unprotected sqlite3_value objects may only be used as arguments
+** to [sqlite3_result_value()], [sqlite3_bind_value()], and
+** [sqlite3_value_dup()].
** The [sqlite3_value_blob | sqlite3_value_type()] family of
** interfaces require protected sqlite3_value objects.
*/
-typedef struct Mem sqlite3_value;
+typedef struct sqlite3_value sqlite3_value;
/*
** CAPI3REF: SQL Function Context Object
@@ -4021,6 +4970,15 @@ typedef struct sqlite3_context sqlite3_context;
** [sqlite3_blob_open | incremental BLOB I/O] routines.
** ^A negative value for the zeroblob results in a zero-length BLOB.
**
+** ^The sqlite3_bind_pointer(S,I,P,T,D) routine causes the I-th parameter in
+** [prepared statement] S to have an SQL value of NULL, but to also be
+** associated with the pointer P of type T. ^D is either a NULL pointer or
+** a pointer to a destructor function for P. ^SQLite will invoke the
+** destructor D with a single argument of P when it is finished using
+** P. The T parameter should be a static string, preferably a string
+** literal. The sqlite3_bind_pointer() routine is part of the
+** [pointer passing interface] added for SQLite 3.20.0.
+**
** ^If any of the sqlite3_bind_*() routines are called with a NULL pointer
** for the [prepared statement] or with a prepared statement for which
** [sqlite3_step()] has been called more recently than [sqlite3_reset()],
@@ -4054,6 +5012,7 @@ SQLITE_API int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)
SQLITE_API int sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64,
void(*)(void*), unsigned char encoding);
SQLITE_API int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
+SQLITE_API int sqlite3_bind_pointer(sqlite3_stmt*, int, void*, const char*,void(*)(void*));
SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
SQLITE_API int sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64);
@@ -4097,8 +5056,8 @@ SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt*);
** ^If the value N is out of range or if the N-th parameter is
** nameless, then NULL is returned. ^The returned string is
** always in UTF-8 encoding even if the named parameter was
-** originally specified as UTF-16 in [sqlite3_prepare16()] or
-** [sqlite3_prepare16_v2()].
+** originally specified as UTF-16 in [sqlite3_prepare16()],
+** [sqlite3_prepare16_v2()], or [sqlite3_prepare16_v3()].
**
** See also: [sqlite3_bind_blob|sqlite3_bind()],
** [sqlite3_bind_parameter_count()], and
@@ -4115,7 +5074,8 @@ SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int);
** parameter to [sqlite3_bind_blob|sqlite3_bind()]. ^A zero
** is returned if no matching parameter is found. ^The parameter
** name must be given in UTF-8 even if the original statement
-** was prepared from UTF-16 text using [sqlite3_prepare16_v2()].
+** was prepared from UTF-16 text using [sqlite3_prepare16_v2()] or
+** [sqlite3_prepare16_v3()].
**
** See also: [sqlite3_bind_blob|sqlite3_bind()],
** [sqlite3_bind_parameter_count()], and
@@ -4138,8 +5098,12 @@ SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt*);
** METHOD: sqlite3_stmt
**
** ^Return the number of columns in the result set returned by the
-** [prepared statement]. ^This routine returns 0 if pStmt is an SQL
-** statement that does not return data (for example an [UPDATE]).
+** [prepared statement]. ^If this routine returns 0, that means the
+** [prepared statement] returns no data (for example an [UPDATE]).
+** ^However, just because this routine returns a positive number does not
+** mean that one or more rows of data will be returned. ^A SELECT statement
+** will always have a positive sqlite3_column_count() but depending on the
+** WHERE clause constraints and the table content, it might return no rows.
**
** See also: [sqlite3_data_count()]
*/
@@ -4265,16 +5229,18 @@ SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
** CAPI3REF: Evaluate An SQL Statement
** METHOD: sqlite3_stmt
**
-** After a [prepared statement] has been prepared using either
-** [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] or one of the legacy
+** After a [prepared statement] has been prepared using any of
+** [sqlite3_prepare_v2()], [sqlite3_prepare_v3()], [sqlite3_prepare16_v2()],
+** or [sqlite3_prepare16_v3()] or one of the legacy
** interfaces [sqlite3_prepare()] or [sqlite3_prepare16()], this function
** must be called one or more times to evaluate the statement.
**
** The details of the behavior of the sqlite3_step() interface depend
-** on whether the statement was prepared using the newer "v2" interface
-** [sqlite3_prepare_v2()] and [sqlite3_prepare16_v2()] or the older legacy
-** interface [sqlite3_prepare()] and [sqlite3_prepare16()]. The use of the
-** new "v2" interface is recommended for new applications but the legacy
+** on whether the statement was prepared using the newer "vX" interfaces
+** [sqlite3_prepare_v3()], [sqlite3_prepare_v2()], [sqlite3_prepare16_v3()],
+** [sqlite3_prepare16_v2()] or the older legacy
+** interfaces [sqlite3_prepare()] and [sqlite3_prepare16()]. The use of the
+** new "vX" interface is recommended for new applications but the legacy
** interface will continue to be supported.
**
** ^In the legacy interface, the return value will be either [SQLITE_BUSY],
@@ -4335,10 +5301,11 @@ SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
** specific [error codes] that better describes the error.
** We admit that this is a goofy design. The problem has been fixed
** with the "v2" interface. If you prepare all of your SQL statements
-** using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] instead
+** using [sqlite3_prepare_v3()] or [sqlite3_prepare_v2()]
+** or [sqlite3_prepare16_v2()] or [sqlite3_prepare16_v3()] instead
** of the legacy [sqlite3_prepare()] and [sqlite3_prepare16()] interfaces,
** then the more specific [error codes] are returned directly
-** by sqlite3_step(). The use of the "v2" interface is recommended.
+** by sqlite3_step(). The use of the "vX" interfaces is recommended.
*/
SQLITE_API int sqlite3_step(sqlite3_stmt*);
@@ -4400,6 +5367,28 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt);
** KEYWORDS: {column access functions}
** METHOD: sqlite3_stmt
**
+** Summary:
+**
+** sqlite3_column_blob | → | BLOB result
+** |
sqlite3_column_double | → | REAL result
+** |
sqlite3_column_int | → | 32-bit INTEGER result
+** |
sqlite3_column_int64 | → | 64-bit INTEGER result
+** |
sqlite3_column_text | → | UTF-8 TEXT result
+** |
sqlite3_column_text16 | → | UTF-16 TEXT result
+** |
sqlite3_column_value | → | The result as an
+** [sqlite3_value|unprotected sqlite3_value] object.
+** |
| |
+** |
sqlite3_column_bytes | → | Size of a BLOB
+** or a UTF-8 TEXT result in bytes
+** |
sqlite3_column_bytes16
+** | → | Size of UTF-16
+** TEXT in bytes
+** |
sqlite3_column_type | → | Default
+** datatype of the result
+** |
+**
+** Details:
+**
** ^These routines return information about a single column of the current
** result row of a query. ^In every case the first argument is a pointer
** to the [prepared statement] that is being evaluated (the [sqlite3_stmt*]
@@ -4421,16 +5410,29 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt);
** are called from a different thread while any of these routines
** are pending, then the results are undefined.
**
+** The first six interfaces (_blob, _double, _int, _int64, _text, and _text16)
+** each return the value of a result column in a specific data format. If
+** the result column is not initially in the requested format (for example,
+** if the query returns an integer but the sqlite3_column_text() interface
+** is used to extract the value) then an automatic type conversion is performed.
+**
** ^The sqlite3_column_type() routine returns the
** [SQLITE_INTEGER | datatype code] for the initial data type
** of the result column. ^The returned value is one of [SQLITE_INTEGER],
-** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL]. The value
-** returned by sqlite3_column_type() is only meaningful if no type
-** conversions have occurred as described below. After a type conversion,
-** the value returned by sqlite3_column_type() is undefined. Future
+** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL].
+** The return value of sqlite3_column_type() can be used to decide which
+** of the first six interface should be used to extract the column value.
+** The value returned by sqlite3_column_type() is only meaningful if no
+** automatic type conversions have occurred for the value in question.
+** After a type conversion, the result of calling sqlite3_column_type()
+** is undefined, though harmless. Future
** versions of SQLite may change the behavior of sqlite3_column_type()
** following a type conversion.
**
+** If the result is a BLOB or a TEXT string, then the sqlite3_column_bytes()
+** or sqlite3_column_bytes16() interfaces can be used to determine the size
+** of that BLOB or string.
+**
** ^If the result is a BLOB or UTF-8 string then the sqlite3_column_bytes()
** routine returns the number of bytes in that BLOB or string.
** ^If the result is a UTF-16 string, then sqlite3_column_bytes() converts
@@ -4467,9 +5469,13 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt);
** [sqlite3_column_value()] is used in any other way, including calls
** to routines like [sqlite3_value_int()], [sqlite3_value_text()],
** or [sqlite3_value_bytes()], the behavior is not threadsafe.
+** Hence, the sqlite3_column_value() interface
+** is normally only useful within the implementation of
+** [application-defined SQL functions] or [virtual tables], not within
+** top-level application code.
**
-** These routines attempt to convert the value where appropriate. ^For
-** example, if the internal representation is FLOAT and a text result
+** The these routines may attempt to convert the datatype of the result.
+** ^For example, if the internal representation is FLOAT and a text result
** is requested, [sqlite3_snprintf()] is used internally to perform the
** conversion automatically. ^(The following table details the conversions
** that are applied:
@@ -4541,7 +5547,7 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt);
** ^The pointers returned are valid until a type conversion occurs as
** described above, or until [sqlite3_step()] or [sqlite3_reset()] or
** [sqlite3_finalize()] is called. ^The memory space used to hold strings
-** and BLOBs is freed automatically. Do not pass the pointers returned
+** and BLOBs is freed automatically. Do not pass the pointers returned
** from [sqlite3_column_blob()], [sqlite3_column_text()], etc. into
** [sqlite3_free()].
**
@@ -4552,15 +5558,15 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt);
** [SQLITE_NOMEM].)^
*/
SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);
-SQLITE_API int sqlite3_column_bytes(sqlite3_stmt*, int iCol);
-SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt*, int iCol);
SQLITE_API double sqlite3_column_double(sqlite3_stmt*, int iCol);
SQLITE_API int sqlite3_column_int(sqlite3_stmt*, int iCol);
SQLITE_API sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol);
SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);
SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt*, int iCol);
-SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol);
SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol);
+SQLITE_API int sqlite3_column_bytes(sqlite3_stmt*, int iCol);
+SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt*, int iCol);
+SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol);
/*
** CAPI3REF: Destroy A Prepared Statement Object
@@ -4794,21 +5800,43 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6
** CAPI3REF: Obtaining SQL Values
** METHOD: sqlite3_value
**
-** The C-language implementation of SQL functions and aggregates uses
-** this set of interface routines to access the parameter values on
-** the function or aggregate.
-**
-** 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 3rd parameter to these callbacks is an array of pointers to
-** [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.
+** Summary:
+**
+** sqlite3_value_blob | → | BLOB value
+** |
sqlite3_value_double | → | REAL value
+** |
sqlite3_value_int | → | 32-bit INTEGER value
+** |
sqlite3_value_int64 | → | 64-bit INTEGER value
+** |
sqlite3_value_pointer | → | Pointer value
+** |
sqlite3_value_text | → | UTF-8 TEXT value
+** |
sqlite3_value_text16 | → | UTF-16 TEXT value in
+** the native byteorder
+** |
sqlite3_value_text16be | → | UTF-16be TEXT value
+** |
sqlite3_value_text16le | → | UTF-16le TEXT value
+** |
| |
+** |
sqlite3_value_bytes | → | Size of a BLOB
+** or a UTF-8 TEXT in bytes
+** |
sqlite3_value_bytes16
+** | → | Size of UTF-16
+** TEXT in bytes
+** |
sqlite3_value_type | → | Default
+** datatype of the value
+** |
sqlite3_value_numeric_type
+** | → | Best numeric datatype of the value
+** |
sqlite3_value_nochange
+** | → | True if the column is unchanged in an UPDATE
+** against a virtual table.
+** |
+**
+** Details:
+**
+** These routines extract type, size, and content information from
+** [protected sqlite3_value] objects. Protected sqlite3_value objects
+** are used to pass parameter information into implementation of
+** [application-defined SQL functions] and [virtual tables].
**
** 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.
+** is not threadsafe.
**
** ^These routines work just like the corresponding [column access functions]
** except that these routines take a single [protected sqlite3_value] object
@@ -4819,6 +5847,24 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6
** sqlite3_value_text16be() and sqlite3_value_text16le() interfaces
** extract UTF-16 strings as big-endian and little-endian respectively.
**
+** ^If [sqlite3_value] object V was initialized
+** using [sqlite3_bind_pointer(S,I,P,X,D)] or [sqlite3_result_pointer(C,P,X,D)]
+** and if X and Y are strings that compare equal according to strcmp(X,Y),
+** then sqlite3_value_pointer(V,Y) will return the pointer P. ^Otherwise,
+** sqlite3_value_pointer(V,Y) returns a NULL. The sqlite3_bind_pointer()
+** routine is part of the [pointer passing interface] added for SQLite 3.20.0.
+**
+** ^(The sqlite3_value_type(V) interface returns the
+** [SQLITE_INTEGER | datatype code] for the initial datatype of the
+** [sqlite3_value] object V. The returned value is one of [SQLITE_INTEGER],
+** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL].)^
+** Other interfaces might change the datatype for an sqlite3_value object.
+** For example, if the datatype is initially SQLITE_INTEGER and
+** sqlite3_value_text(V) is called to extract a text value for that
+** integer, then subsequent calls to sqlite3_value_type(V) might return
+** SQLITE_TEXT. Whether or not a persistent internal datatype conversion
+** occurs is undefined and may change from one release of SQLite to the next.
+**
** ^(The sqlite3_value_numeric_type() interface attempts to apply
** numeric affinity to the value. This means that an attempt is
** made to convert the value to an integer or floating point. If
@@ -4827,6 +5873,19 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6
** then the conversion is performed. Otherwise no conversion occurs.
** The [SQLITE_INTEGER | datatype] after conversion is returned.)^
**
+** ^Within the [xUpdate] method of a [virtual table], the
+** sqlite3_value_nochange(X) interface returns true if and only if
+** the column corresponding to X is unchanged by the UPDATE operation
+** that the xUpdate method call was invoked to implement and if
+** and the prior [xColumn] method call that was invoked to extracted
+** the value for that column returned without setting a result (probably
+** because it queried [sqlite3_vtab_nochange()] and found that the column
+** was unchanging). ^Within an [xUpdate] method, any value for which
+** sqlite3_value_nochange(X) is true will in all other respects appear
+** to be a NULL value. If sqlite3_value_nochange(X) is invoked anywhere other
+** than within an [xUpdate] method call for an UPDATE statement, then
+** the return value is arbitrary and meaningless.
+**
** Please pay particular attention to the fact that the pointer returned
** from [sqlite3_value_blob()], [sqlite3_value_text()], or
** [sqlite3_value_text16()] can be invalidated by a subsequent call to
@@ -4837,17 +5896,19 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6
** the SQL function that supplied the [sqlite3_value*] parameters.
*/
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*);
SQLITE_API double sqlite3_value_double(sqlite3_value*);
SQLITE_API int sqlite3_value_int(sqlite3_value*);
SQLITE_API sqlite3_int64 sqlite3_value_int64(sqlite3_value*);
+SQLITE_API void *sqlite3_value_pointer(sqlite3_value*, const char*);
SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value*);
SQLITE_API const void *sqlite3_value_text16(sqlite3_value*);
SQLITE_API const void *sqlite3_value_text16le(sqlite3_value*);
SQLITE_API const void *sqlite3_value_text16be(sqlite3_value*);
+SQLITE_API int sqlite3_value_bytes(sqlite3_value*);
+SQLITE_API int sqlite3_value_bytes16(sqlite3_value*);
SQLITE_API int sqlite3_value_type(sqlite3_value*);
SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*);
+SQLITE_API int sqlite3_value_nochange(sqlite3_value*);
/*
** CAPI3REF: Finding The Subtype Of SQL Values
@@ -4858,10 +5919,6 @@ SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*);
** information can be used to pass a limited amount of context from
** one SQL function to another. Use the [sqlite3_result_subtype()]
** routine to set the subtype for the return value of an SQL function.
-**
-** SQLite makes no use of subtype itself. It merely passes the subtype
-** from the result of one [application-defined SQL function] into the
-** input of another.
*/
SQLITE_API unsigned int sqlite3_value_subtype(sqlite3_value*);
@@ -4969,10 +6026,11 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
** the compiled regular expression can be reused on multiple
** invocations of the same function.
**
-** ^The sqlite3_get_auxdata() interface returns a pointer to the metadata
-** associated by the sqlite3_set_auxdata() function with the Nth argument
-** value to the application-defined function. ^If there is no metadata
-** associated with the function argument, this sqlite3_get_auxdata() interface
+** ^The sqlite3_get_auxdata(C,N) interface returns a pointer to the metadata
+** associated by the sqlite3_set_auxdata(C,N,P,X) function with the Nth argument
+** value to the application-defined function. ^N is zero for the left-most
+** function argument. ^If there is no metadata
+** associated with the function argument, the sqlite3_get_auxdata(C,N) interface
** returns a NULL pointer.
**
** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as metadata for the N-th
@@ -5003,6 +6061,10 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
** function parameters that are compile-time constants, including literal
** values and [parameters] and expressions composed from the same.)^
**
+** The value of the N parameter to these interfaces should be non-negative.
+** Future enhancements may make use of negative N values to define new
+** kinds of function caching behavior.
+**
** These routines must be called from the same thread in which
** the SQL function is running.
*/
@@ -5126,7 +6188,7 @@ typedef void (*sqlite3_destructor_type)(void*);
** when it has finished using that result.
** ^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
+** then SQLite makes a copy of the result into space obtained
** from [sqlite3_malloc()] before it returns.
**
** ^The sqlite3_result_value() interface sets the result of
@@ -5139,6 +6201,17 @@ typedef void (*sqlite3_destructor_type)(void*);
** [unprotected sqlite3_value] object is required, so either
** kind of [sqlite3_value] object can be used with this interface.
**
+** ^The sqlite3_result_pointer(C,P,T,D) interface sets the result to an
+** SQL NULL value, just like [sqlite3_result_null(C)], except that it
+** also associates the host-language pointer P or type T with that
+** NULL value such that the pointer can be retrieved within an
+** [application-defined SQL function] using [sqlite3_value_pointer()].
+** ^If the D parameter is not NULL, then it is a pointer to a destructor
+** for the P parameter. ^SQLite invokes D with P as its only argument
+** when SQLite is finished with P. The T parameter should be a static
+** string and preferably a string literal. The sqlite3_result_pointer()
+** routine is part of the [pointer passing interface] added for SQLite 3.20.0.
+**
** If these routines are called from within the different thread
** than the one containing the application-defined function that received
** the [sqlite3_context] pointer, the results are undefined.
@@ -5162,6 +6235,7 @@ SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*
SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*));
SQLITE_API void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*));
SQLITE_API void sqlite3_result_value(sqlite3_context*, sqlite3_value*);
+SQLITE_API void sqlite3_result_pointer(sqlite3_context*, void*,const char*,void(*)(void*));
SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n);
SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n);
@@ -5648,7 +6722,7 @@ SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
** ^The update hook is not invoked when [WITHOUT ROWID] tables are modified.
**
** ^In the current implementation, the update hook
-** is not invoked when duplication rows are deleted because of an
+** is not invoked when conflicting rows are deleted because of an
** [ON CONFLICT | ON CONFLICT REPLACE] clause. ^Nor is the update hook
** invoked when rows are deleted using the [truncate optimization].
** The exceptions defined in this paragraph might change in a future
@@ -5821,7 +6895,9 @@ SQLITE_API SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N);
** ^If the column-name parameter to sqlite3_table_column_metadata() is a
** NULL pointer, then this routine simply checks for the existence of the
** table and returns SQLITE_OK if the table exists and SQLITE_ERROR if it
-** does not.
+** does not. If the table name parameter T in a call to
+** sqlite3_table_column_metadata(X,D,T,C,...) is NULL then the result is
+** undefined behavior.
**
** ^The column is identified by the second, third and fourth parameters to
** this function. ^(The second parameter is either the name of the database
@@ -6231,15 +7307,20 @@ struct sqlite3_index_info {
** an operator that is part of a constraint term in the wHERE clause of
** a query that uses a [virtual table].
*/
-#define SQLITE_INDEX_CONSTRAINT_EQ 2
-#define SQLITE_INDEX_CONSTRAINT_GT 4
-#define SQLITE_INDEX_CONSTRAINT_LE 8
-#define SQLITE_INDEX_CONSTRAINT_LT 16
-#define SQLITE_INDEX_CONSTRAINT_GE 32
-#define SQLITE_INDEX_CONSTRAINT_MATCH 64
-#define SQLITE_INDEX_CONSTRAINT_LIKE 65
-#define SQLITE_INDEX_CONSTRAINT_GLOB 66
-#define SQLITE_INDEX_CONSTRAINT_REGEXP 67
+#define SQLITE_INDEX_CONSTRAINT_EQ 2
+#define SQLITE_INDEX_CONSTRAINT_GT 4
+#define SQLITE_INDEX_CONSTRAINT_LE 8
+#define SQLITE_INDEX_CONSTRAINT_LT 16
+#define SQLITE_INDEX_CONSTRAINT_GE 32
+#define SQLITE_INDEX_CONSTRAINT_MATCH 64
+#define SQLITE_INDEX_CONSTRAINT_LIKE 65
+#define SQLITE_INDEX_CONSTRAINT_GLOB 66
+#define SQLITE_INDEX_CONSTRAINT_REGEXP 67
+#define SQLITE_INDEX_CONSTRAINT_NE 68
+#define SQLITE_INDEX_CONSTRAINT_ISNOT 69
+#define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70
+#define SQLITE_INDEX_CONSTRAINT_ISNULL 71
+#define SQLITE_INDEX_CONSTRAINT_IS 72
/*
** CAPI3REF: Register A Virtual Table Implementation
@@ -6430,6 +7511,12 @@ typedef struct sqlite3_blob sqlite3_blob;
** [database connection] error code and message accessible via
** [sqlite3_errcode()] and [sqlite3_errmsg()] and related functions.
**
+** A BLOB referenced by sqlite3_blob_open() may be read using the
+** [sqlite3_blob_read()] interface and modified by using
+** [sqlite3_blob_write()]. The [BLOB handle] can be moved to a
+** different row of the same table using the [sqlite3_blob_reopen()]
+** interface. However, the column, table, or database of a [BLOB handle]
+** cannot be changed after the [BLOB handle] is opened.
**
** ^(If the row that a BLOB handle points to is modified by an
** [UPDATE], [DELETE], or by [ON CONFLICT] side-effects
@@ -6453,6 +7540,10 @@ typedef struct sqlite3_blob sqlite3_blob;
**
** To avoid a resource leak, every open [BLOB handle] should eventually
** be released by a call to [sqlite3_blob_close()].
+**
+** See also: [sqlite3_blob_close()],
+** [sqlite3_blob_reopen()], [sqlite3_blob_read()],
+** [sqlite3_blob_bytes()], [sqlite3_blob_write()].
*/
SQLITE_API int sqlite3_blob_open(
sqlite3*,
@@ -6468,11 +7559,11 @@ SQLITE_API int sqlite3_blob_open(
** CAPI3REF: Move a BLOB Handle to a New Row
** METHOD: sqlite3_blob
**
-** ^This function is used to move an existing blob handle so that it points
+** ^This function is used to move an existing [BLOB handle] so that it points
** to a different row of the same database table. ^The new row is identified
** by the rowid value passed as the second argument. Only the row can be
** changed. ^The database, table and column on which the blob handle is open
-** remain the same. Moving an existing blob handle to a new row can be
+** remain the same. Moving an existing [BLOB handle] to a new row is
** faster than closing the existing handle and opening a new one.
**
** ^(The new row must meet the same criteria as for [sqlite3_blob_open()] -
@@ -6920,9 +8011,9 @@ SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*);
** the xFileControl method. ^The return value of the xFileControl
** method becomes the return value of this routine.
**
-** ^The SQLITE_FCNTL_FILE_POINTER value for the op parameter causes
+** ^The [SQLITE_FCNTL_FILE_POINTER] value for the op parameter causes
** a pointer to the underlying [sqlite3_file] object to be written into
-** the space pointed to by the 4th parameter. ^The SQLITE_FCNTL_FILE_POINTER
+** the space pointed to by the 4th parameter. ^The [SQLITE_FCNTL_FILE_POINTER]
** case is a short-circuit path which does not actually invoke the
** underlying sqlite3_io_methods.xFileControl method.
**
@@ -6934,7 +8025,7 @@ SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*);
** an incorrect zDbName and an SQLITE_ERROR return from the underlying
** xFileControl method.
**
-** See also: [SQLITE_FCNTL_LOCKSTATE]
+** See also: [file control opcodes]
*/
SQLITE_API int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*);
@@ -6981,7 +8072,7 @@ SQLITE_API int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_RESERVE 14
#define SQLITE_TESTCTRL_OPTIMIZATIONS 15
#define SQLITE_TESTCTRL_ISKEYWORD 16
-#define SQLITE_TESTCTRL_SCRATCHMALLOC 17
+#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */
#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18
#define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */
#define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD 19
@@ -6991,7 +8082,8 @@ SQLITE_API int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_ISINIT 23
#define SQLITE_TESTCTRL_SORTER_MMAP 24
#define SQLITE_TESTCTRL_IMPOSTER 25
-#define SQLITE_TESTCTRL_LAST 25
+#define SQLITE_TESTCTRL_PARSER_COVERAGE 26
+#define SQLITE_TESTCTRL_LAST 26 /* Largest TESTCTRL */
/*
** CAPI3REF: SQLite Runtime Status
@@ -7040,8 +8132,7 @@ SQLITE_API int sqlite3_status64(
** This parameter is the current amount of memory checked out
** using [sqlite3_malloc()], either directly or indirectly. The
** figure includes calls made to [sqlite3_malloc()] by the application
-** and internal memory usage by the SQLite library. Scratch memory
-** controlled by [SQLITE_CONFIG_SCRATCH] and auxiliary page-cache
+** and internal memory usage by the SQLite library. Auxiliary page-cache
** memory controlled by [SQLITE_CONFIG_PAGECACHE] is not included in
** this parameter. The amount returned is the sum of the allocation
** sizes as reported by the xSize method in [sqlite3_mem_methods].)^
@@ -7079,29 +8170,14 @@ SQLITE_API int sqlite3_status64(
** *pHighwater parameter to [sqlite3_status()] is of interest.
** The value written into the *pCurrent parameter is undefined.)^
**
-** [[SQLITE_STATUS_SCRATCH_USED]] ^(SQLITE_STATUS_SCRATCH_USED
-** This parameter returns the number of allocations used out of the
-** [scratch memory allocator] configured using
-** [SQLITE_CONFIG_SCRATCH]. The value returned is in allocations, not
-** in bytes. Since a single thread may only have one scratch allocation
-** outstanding at time, this parameter also reports the number of threads
-** using scratch memory at the same time.)^
+** [[SQLITE_STATUS_SCRATCH_USED]] SQLITE_STATUS_SCRATCH_USED
+** No longer used.
**
** [[SQLITE_STATUS_SCRATCH_OVERFLOW]] ^(SQLITE_STATUS_SCRATCH_OVERFLOW
-** This parameter returns the number of bytes of scratch memory
-** allocation which could not be satisfied by the [SQLITE_CONFIG_SCRATCH]
-** buffer and where forced to overflow to [sqlite3_malloc()]. The values
-** returned include overflows because the requested allocation was too
-** larger (that is, because the requested allocation was larger than the
-** "sz" parameter to [SQLITE_CONFIG_SCRATCH]) and because no scratch buffer
-** slots were available.
-** )^
-**
-** [[SQLITE_STATUS_SCRATCH_SIZE]] ^(SQLITE_STATUS_SCRATCH_SIZE
-** This parameter records the largest memory allocation request
-** handed to [scratch memory allocator]. Only the value returned in the
-** *pHighwater parameter to [sqlite3_status()] is of interest.
-** The value written into the *pCurrent parameter is undefined.)^
+** No longer used.
+**
+** [[SQLITE_STATUS_SCRATCH_SIZE]] SQLITE_STATUS_SCRATCH_SIZE
+** No longer used.
**
** [[SQLITE_STATUS_PARSER_STACK]] ^(SQLITE_STATUS_PARSER_STACK
** The *pHighwater parameter records the deepest parser stack.
@@ -7114,12 +8190,12 @@ SQLITE_API int sqlite3_status64(
#define SQLITE_STATUS_MEMORY_USED 0
#define SQLITE_STATUS_PAGECACHE_USED 1
#define SQLITE_STATUS_PAGECACHE_OVERFLOW 2
-#define SQLITE_STATUS_SCRATCH_USED 3
-#define SQLITE_STATUS_SCRATCH_OVERFLOW 4
+#define SQLITE_STATUS_SCRATCH_USED 3 /* NOT USED */
+#define SQLITE_STATUS_SCRATCH_OVERFLOW 4 /* NOT USED */
#define SQLITE_STATUS_MALLOC_SIZE 5
#define SQLITE_STATUS_PARSER_STACK 6
#define SQLITE_STATUS_PAGECACHE_SIZE 7
-#define SQLITE_STATUS_SCRATCH_SIZE 8
+#define SQLITE_STATUS_SCRATCH_SIZE 8 /* NOT USED */
#define SQLITE_STATUS_MALLOC_COUNT 9
/*
@@ -7324,6 +8400,24 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
** used as a proxy for the total work done by the prepared statement.
** If the number of virtual machine operations exceeds 2147483647
** then the value returned by this statement status code is undefined.
+**
+** [[SQLITE_STMTSTATUS_REPREPARE]] SQLITE_STMTSTATUS_REPREPARE
+** ^This is the number of times that the prepare statement has been
+** automatically regenerated due to schema changes or change to
+** [bound parameters] that might affect the query plan.
+**
+** [[SQLITE_STMTSTATUS_RUN]] SQLITE_STMTSTATUS_RUN
+** ^This is the number of times that the prepared statement has
+** been run. A single "run" for the purposes of this counter is one
+** or more calls to [sqlite3_step()] followed by a call to [sqlite3_reset()].
+** The counter is incremented on the first [sqlite3_step()] call of each
+** cycle.
+**
+** [[SQLITE_STMTSTATUS_MEMUSED]] SQLITE_STMTSTATUS_MEMUSED
+** ^This is the approximate number of bytes of heap memory
+** used to store the prepared statement. ^This value is not actually
+** a counter, and so the resetFlg parameter to sqlite3_stmt_status()
+** is ignored when the opcode is SQLITE_STMTSTATUS_MEMUSED.
**
**
*/
@@ -7331,6 +8425,9 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
#define SQLITE_STMTSTATUS_SORT 2
#define SQLITE_STMTSTATUS_AUTOINDEX 3
#define SQLITE_STMTSTATUS_VM_STEP 4
+#define SQLITE_STMTSTATUS_REPREPARE 5
+#define SQLITE_STMTSTATUS_RUN 6
+#define SQLITE_STMTSTATUS_MEMUSED 99
/*
** CAPI3REF: Custom Page Cache Object
@@ -8240,6 +9337,40 @@ SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
*/
SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
+/*
+** CAPI3REF: Determine If Virtual Table Column Access Is For UPDATE
+**
+** If the sqlite3_vtab_nochange(X) routine is called within the [xColumn]
+** method of a [virtual table], then it returns true if and only if the
+** column is being fetched as part of an UPDATE operation during which the
+** column value will not change. Applications might use this to substitute
+** a lighter-weight value to return that the corresponding [xUpdate] method
+** understands as a "no-change" value.
+**
+** If the [xColumn] method calls sqlite3_vtab_nochange() and finds that
+** the column is not changed by the UPDATE statement, they the xColumn
+** method can optionally return without setting a result, without calling
+** any of the [sqlite3_result_int|sqlite3_result_xxxxx() interfaces].
+** In that case, [sqlite3_value_nochange(X)] will return true for the
+** same column in the [xUpdate] method.
+*/
+SQLITE_API int sqlite3_vtab_nochange(sqlite3_context*);
+
+/*
+** CAPI3REF: Determine The Collation For a Virtual Table Constraint
+**
+** This function may only be called from within a call to the [xBestIndex]
+** method of a [virtual table].
+**
+** The first argument must be the sqlite3_index_info object that is the
+** first parameter to the xBestIndex() method. The second argument must be
+** an index into the aConstraint[] array belonging to the sqlite3_index_info
+** structure passed to xBestIndex. This function returns a pointer to a buffer
+** containing the name of the collation sequence for the corresponding
+** constraint.
+*/
+SQLITE_API SQLITE_EXPERIMENTAL const char *sqlite3_vtab_collation(sqlite3_index_info*,int);
+
/*
** CAPI3REF: Conflict resolution modes
** KEYWORDS: {conflict resolution mode}
@@ -8401,7 +9532,7 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*);
**
** ^The [sqlite3_preupdate_hook()] interface registers a callback function
** that is invoked prior to each [INSERT], [UPDATE], and [DELETE] operation
-** on a [rowid table].
+** on a database table.
** ^At most one preupdate hook may be registered at a time on a single
** [database connection]; each call to [sqlite3_preupdate_hook()] overrides
** the previous setting.
@@ -8410,9 +9541,9 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*);
** ^The third parameter to [sqlite3_preupdate_hook()] is passed through as
** the first parameter to callbacks.
**
-** ^The preupdate hook only fires for changes to [rowid tables]; the preupdate
-** hook is not invoked for changes to [virtual tables] or [WITHOUT ROWID]
-** tables.
+** ^The preupdate hook only fires for changes to real database tables; the
+** preupdate hook is not invoked for changes to [virtual tables] or to
+** system tables like sqlite_master or sqlite_stat1.
**
** ^The second parameter to the preupdate callback is a pointer to
** the [database connection] that registered the preupdate hook.
@@ -8426,12 +9557,16 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*);
** databases.)^
** ^The fifth parameter to the preupdate callback is the name of the
** table that is being modified.
-** ^The sixth parameter to the preupdate callback is the initial [rowid] of the
-** row being changes for SQLITE_UPDATE and SQLITE_DELETE changes and is
-** undefined for SQLITE_INSERT changes.
-** ^The seventh parameter to the preupdate callback is the final [rowid] of
-** the row being changed for SQLITE_UPDATE and SQLITE_INSERT changes and is
-** undefined for SQLITE_DELETE changes.
+**
+** For an UPDATE or DELETE operation on a [rowid table], the sixth
+** parameter passed to the preupdate callback is the initial [rowid] of the
+** row being modified or deleted. For an INSERT operation on a rowid table,
+** or any operation on a WITHOUT ROWID table, the value of the sixth
+** parameter is undefined. For an INSERT or UPDATE on a rowid table the
+** seventh parameter is the final rowid value of the row being inserted
+** or updated. The value of the seventh parameter passed to the callback
+** function is not defined for operations on WITHOUT ROWID tables, or for
+** INSERT operations on rowid tables.
**
** The [sqlite3_preupdate_old()], [sqlite3_preupdate_new()],
** [sqlite3_preupdate_count()], and [sqlite3_preupdate_depth()] interfaces
@@ -8471,7 +9606,8 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*);
**
** See also: [sqlite3_update_hook()]
*/
-SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_preupdate_hook(
+#if defined(SQLITE_ENABLE_PREUPDATE_HOOK)
+SQLITE_API void *sqlite3_preupdate_hook(
sqlite3 *db,
void(*xPreUpdate)(
void *pCtx, /* Copy of third arg to preupdate_hook() */
@@ -8484,10 +9620,11 @@ SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_preupdate_hook(
),
void*
);
-SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **);
-SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_preupdate_count(sqlite3 *);
-SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_preupdate_depth(sqlite3 *);
-SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **);
+SQLITE_API int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **);
+SQLITE_API int sqlite3_preupdate_count(sqlite3 *);
+SQLITE_API int sqlite3_preupdate_depth(sqlite3 *);
+SQLITE_API int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **);
+#endif
/*
** CAPI3REF: Low-level system error code
@@ -8503,7 +9640,7 @@ SQLITE_API int sqlite3_system_errno(sqlite3*);
/*
** CAPI3REF: Database Snapshot
-** KEYWORDS: {snapshot}
+** KEYWORDS: {snapshot} {sqlite3_snapshot}
** EXPERIMENTAL
**
** An instance of the snapshot object records the state of a [WAL mode]
@@ -8527,7 +9664,9 @@ SQLITE_API int sqlite3_system_errno(sqlite3*);
** to an historical snapshot (if possible). The destructor for
** sqlite3_snapshot objects is [sqlite3_snapshot_free()].
*/
-typedef struct sqlite3_snapshot sqlite3_snapshot;
+typedef struct sqlite3_snapshot {
+ unsigned char hidden[48];
+} sqlite3_snapshot;
/*
** CAPI3REF: Record A Database Snapshot
@@ -8538,9 +9677,32 @@ typedef struct sqlite3_snapshot sqlite3_snapshot;
** schema S in database connection D. ^On success, the
** [sqlite3_snapshot_get(D,S,P)] interface writes a pointer to the newly
** created [sqlite3_snapshot] object into *P and returns SQLITE_OK.
-** ^If schema S of [database connection] D is not a [WAL mode] database
-** that is in a read transaction, then [sqlite3_snapshot_get(D,S,P)]
-** leaves the *P value unchanged and returns an appropriate [error code].
+** If there is not already a read-transaction open on schema S when
+** this function is called, one is opened automatically.
+**
+** The following must be true for this function to succeed. If any of
+** the following statements are false when sqlite3_snapshot_get() is
+** called, SQLITE_ERROR is returned. The final value of *P is undefined
+** in this case.
+**
+**
+** - The database handle must be in [autocommit mode].
+**
+**
- Schema S of [database connection] D must be a [WAL mode] database.
+**
+**
- There must not be a write transaction open on schema S of database
+** connection D.
+**
+**
- One or more transactions must have been written to the current wal
+** file since it was created on disk (by any connection). This means
+** that a snapshot cannot be taken on a wal mode database with no wal
+** file immediately after it is first opened. At least one transaction
+** must be written to it first.
+**
+**
+** This function may also return SQLITE_NOMEM. If it is called with the
+** database handle in autocommit mode but fails for some other reason,
+** whether or not a read transaction is opened on schema S is undefined.
**
** The [sqlite3_snapshot] object returned from a successful call to
** [sqlite3_snapshot_get()] must be freed using [sqlite3_snapshot_free()]
@@ -8633,6 +9795,28 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp(
sqlite3_snapshot *p2
);
+/*
+** CAPI3REF: Recover snapshots from a wal file
+** EXPERIMENTAL
+**
+** If all connections disconnect from a database file but do not perform
+** a checkpoint, the existing wal file is opened along with the database
+** file the next time the database is opened. At this point it is only
+** possible to successfully call sqlite3_snapshot_open() to open the most
+** recent snapshot of the database (the one at the head of the wal file),
+** even though the wal file may contain other valid snapshots for which
+** clients have sqlite3_snapshot handles.
+**
+** This function attempts to scan the wal file associated with database zDb
+** of database handle db and make all valid snapshots available to
+** sqlite3_snapshot_open(). It is an error if there is already a read
+** transaction open on the database, or if the database is not a wal mode
+** database.
+**
+** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
+*/
+SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb);
+
/*
** Undo the hack that converts floating point types to integer for
** builds on processors without floating point support.
@@ -8818,7 +10002,7 @@ typedef struct sqlite3_changeset_iter sqlite3_changeset_iter;
** attached database. It is not an error if database zDb is not attached
** to the database when the session object is created.
*/
-int sqlite3session_create(
+SQLITE_API int sqlite3session_create(
sqlite3 *db, /* Database handle */
const char *zDb, /* Name of db (e.g. "main") */
sqlite3_session **ppSession /* OUT: New session object */
@@ -8836,7 +10020,7 @@ int sqlite3session_create(
** are attached is closed. Refer to the documentation for
** [sqlite3session_create()] for details.
*/
-void sqlite3session_delete(sqlite3_session *pSession);
+SQLITE_API void sqlite3session_delete(sqlite3_session *pSession);
/*
@@ -8856,7 +10040,7 @@ void sqlite3session_delete(sqlite3_session *pSession);
** The return value indicates the final state of the session object: 0 if
** the session is disabled, or 1 if it is enabled.
*/
-int sqlite3session_enable(sqlite3_session *pSession, int bEnable);
+SQLITE_API int sqlite3session_enable(sqlite3_session *pSession, int bEnable);
/*
** CAPI3REF: Set Or Clear the Indirect Change Flag
@@ -8885,7 +10069,7 @@ int sqlite3session_enable(sqlite3_session *pSession, int bEnable);
** The return value indicates the final state of the indirect flag: 0 if
** it is clear, or 1 if it is set.
*/
-int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect);
+SQLITE_API int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect);
/*
** CAPI3REF: Attach A Table To A Session Object
@@ -8914,8 +10098,37 @@ int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect);
**
** SQLITE_OK is returned if the call completes without error. Or, if an error
** occurs, an SQLite error code (e.g. SQLITE_NOMEM) is returned.
+**
+** Special sqlite_stat1 Handling
+**
+** As of SQLite version 3.22.0, the "sqlite_stat1" table is an exception to
+** some of the rules above. In SQLite, the schema of sqlite_stat1 is:
+**
+** CREATE TABLE sqlite_stat1(tbl,idx,stat)
+**
+**
+** Even though sqlite_stat1 does not have a PRIMARY KEY, changes are
+** recorded for it as if the PRIMARY KEY is (tbl,idx). Additionally, changes
+** are recorded for rows for which (idx IS NULL) is true. However, for such
+** rows a zero-length blob (SQL value X'') is stored in the changeset or
+** patchset instead of a NULL value. This allows such changesets to be
+** manipulated by legacy implementations of sqlite3changeset_invert(),
+** concat() and similar.
+**
+** The sqlite3changeset_apply() function automatically converts the
+** zero-length blob back to a NULL value when updating the sqlite_stat1
+** table. However, if the application calls sqlite3changeset_new(),
+** sqlite3changeset_old() or sqlite3changeset_conflict on a changeset
+** iterator directly (including on a changeset iterator passed to a
+** conflict-handler callback) then the X'' value is returned. The application
+** must translate X'' to NULL itself if required.
+**
+** Legacy (older than 3.22.0) versions of the sessions module cannot capture
+** changes made to the sqlite_stat1 table. Legacy versions of the
+** sqlite3changeset_apply() function silently ignore any modifications to the
+** sqlite_stat1 table that are part of a changeset or patchset.
*/
-int sqlite3session_attach(
+SQLITE_API int sqlite3session_attach(
sqlite3_session *pSession, /* Session object */
const char *zTab /* Table name */
);
@@ -8929,7 +10142,7 @@ int sqlite3session_attach(
** If xFilter returns 0, changes is not tracked. Note that once a table is
** attached, xFilter will not be called again.
*/
-void sqlite3session_table_filter(
+SQLITE_API void sqlite3session_table_filter(
sqlite3_session *pSession, /* Session object */
int(*xFilter)(
void *pCtx, /* Copy of third arg to _filter_table() */
@@ -9042,7 +10255,7 @@ void sqlite3session_table_filter(
** another field of the same row is updated while the session is enabled, the
** resulting changeset will contain an UPDATE change that updates both fields.
*/
-int sqlite3session_changeset(
+SQLITE_API int sqlite3session_changeset(
sqlite3_session *pSession, /* Session object */
int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */
void **ppChangeset /* OUT: Buffer containing changeset */
@@ -9086,7 +10299,8 @@ int sqlite3session_changeset(
** the from-table, a DELETE record is added to the session object.
**
** For each row (primary key) that exists in both tables, but features
-** different in each, an UPDATE record is added to the session.
+** different non-PK values in each, an UPDATE record is added to the
+** session.
**
**
** To clarify, if this function is called and then a changeset constructed
@@ -9103,7 +10317,7 @@ int sqlite3session_changeset(
** message. It is the responsibility of the caller to free this buffer using
** sqlite3_free().
*/
-int sqlite3session_diff(
+SQLITE_API int sqlite3session_diff(
sqlite3_session *pSession,
const char *zFromDb,
const char *zTbl,
@@ -9139,10 +10353,10 @@ int sqlite3session_diff(
** a single table are grouped together, tables appear in the order in which
** they were attached to the session object).
*/
-int sqlite3session_patchset(
+SQLITE_API int sqlite3session_patchset(
sqlite3_session *pSession, /* Session object */
- int *pnPatchset, /* OUT: Size of buffer at *ppChangeset */
- void **ppPatchset /* OUT: Buffer containing changeset */
+ int *pnPatchset, /* OUT: Size of buffer at *ppPatchset */
+ void **ppPatchset /* OUT: Buffer containing patchset */
);
/*
@@ -9160,7 +10374,7 @@ int sqlite3session_patchset(
** guaranteed that a call to sqlite3session_changeset() will return a
** changeset containing zero changes.
*/
-int sqlite3session_isempty(sqlite3_session *pSession);
+SQLITE_API int sqlite3session_isempty(sqlite3_session *pSession);
/*
** CAPI3REF: Create An Iterator To Traverse A Changeset
@@ -9195,7 +10409,7 @@ int sqlite3session_isempty(sqlite3_session *pSession);
** the applies to table X, then one for table Y, and then later on visit
** another change for table X.
*/
-int sqlite3changeset_start(
+SQLITE_API int sqlite3changeset_start(
sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */
int nChangeset, /* Size of changeset blob in bytes */
void *pChangeset /* Pointer to blob containing changeset */
@@ -9224,7 +10438,7 @@ int sqlite3changeset_start(
** codes include SQLITE_CORRUPT (if the changeset buffer is corrupt) or
** SQLITE_NOMEM.
*/
-int sqlite3changeset_next(sqlite3_changeset_iter *pIter);
+SQLITE_API int sqlite3changeset_next(sqlite3_changeset_iter *pIter);
/*
** CAPI3REF: Obtain The Current Operation From A Changeset Iterator
@@ -9252,7 +10466,7 @@ int sqlite3changeset_next(sqlite3_changeset_iter *pIter);
** SQLite error code is returned. The values of the output variables may not
** be trusted in this case.
*/
-int sqlite3changeset_op(
+SQLITE_API int sqlite3changeset_op(
sqlite3_changeset_iter *pIter, /* Iterator object */
const char **pzTab, /* OUT: Pointer to table name */
int *pnCol, /* OUT: Number of columns in table */
@@ -9285,7 +10499,7 @@ int sqlite3changeset_op(
** SQLITE_OK is returned and the output variables populated as described
** above.
*/
-int sqlite3changeset_pk(
+SQLITE_API int sqlite3changeset_pk(
sqlite3_changeset_iter *pIter, /* Iterator object */
unsigned char **pabPK, /* OUT: Array of boolean - true for PK cols */
int *pnCol /* OUT: Number of entries in output array */
@@ -9315,7 +10529,7 @@ int sqlite3changeset_pk(
** If some other error occurs (e.g. an OOM condition), an SQLite error code
** is returned and *ppValue is set to NULL.
*/
-int sqlite3changeset_old(
+SQLITE_API int sqlite3changeset_old(
sqlite3_changeset_iter *pIter, /* Changeset iterator */
int iVal, /* Column number */
sqlite3_value **ppValue /* OUT: Old value (or NULL pointer) */
@@ -9348,7 +10562,7 @@ int sqlite3changeset_old(
** If some other error occurs (e.g. an OOM condition), an SQLite error code
** is returned and *ppValue is set to NULL.
*/
-int sqlite3changeset_new(
+SQLITE_API int sqlite3changeset_new(
sqlite3_changeset_iter *pIter, /* Changeset iterator */
int iVal, /* Column number */
sqlite3_value **ppValue /* OUT: New value (or NULL pointer) */
@@ -9375,7 +10589,7 @@ int sqlite3changeset_new(
** If some other error occurs (e.g. an OOM condition), an SQLite error code
** is returned and *ppValue is set to NULL.
*/
-int sqlite3changeset_conflict(
+SQLITE_API int sqlite3changeset_conflict(
sqlite3_changeset_iter *pIter, /* Changeset iterator */
int iVal, /* Column number */
sqlite3_value **ppValue /* OUT: Value from conflicting row */
@@ -9391,7 +10605,7 @@ int sqlite3changeset_conflict(
**
** In all other cases this function returns SQLITE_MISUSE.
*/
-int sqlite3changeset_fk_conflicts(
+SQLITE_API int sqlite3changeset_fk_conflicts(
sqlite3_changeset_iter *pIter, /* Changeset iterator */
int *pnOut /* OUT: Number of FK violations */
);
@@ -9424,7 +10638,7 @@ int sqlite3changeset_fk_conflicts(
** // An error has occurred
** }
*/
-int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter);
+SQLITE_API int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter);
/*
** CAPI3REF: Invert A Changeset
@@ -9454,7 +10668,7 @@ int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter);
** WARNING/TODO: This function currently assumes that the input is a valid
** changeset. If it is not, the results are undefined.
*/
-int sqlite3changeset_invert(
+SQLITE_API int sqlite3changeset_invert(
int nIn, const void *pIn, /* Input changeset */
int *pnOut, void **ppOut /* OUT: Inverse of input */
);
@@ -9483,7 +10697,7 @@ int sqlite3changeset_invert(
**
** Refer to the sqlite3_changegroup documentation below for details.
*/
-int sqlite3changeset_concat(
+SQLITE_API int sqlite3changeset_concat(
int nA, /* Number of bytes in buffer pA */
void *pA, /* Pointer to buffer containing changeset A */
int nB, /* Number of bytes in buffer pB */
@@ -9533,7 +10747,7 @@ typedef struct sqlite3_changegroup sqlite3_changegroup;
** sqlite3changegroup_output() functions, also available are the streaming
** versions sqlite3changegroup_add_strm() and sqlite3changegroup_output_strm().
*/
-int sqlite3changegroup_new(sqlite3_changegroup **pp);
+SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp);
/*
** CAPI3REF: Add A Changeset To A Changegroup
@@ -9610,7 +10824,7 @@ int sqlite3changegroup_new(sqlite3_changegroup **pp);
**
** If no error occurs, SQLITE_OK is returned.
*/
-int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData);
+SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData);
/*
** CAPI3REF: Obtain A Composite Changeset From A Changegroup
@@ -9636,7 +10850,7 @@ int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData);
** responsibility of the caller to eventually free the buffer using a
** call to sqlite3_free().
*/
-int sqlite3changegroup_output(
+SQLITE_API int sqlite3changegroup_output(
sqlite3_changegroup*,
int *pnData, /* OUT: Size of output buffer in bytes */
void **ppData /* OUT: Pointer to output buffer */
@@ -9645,7 +10859,7 @@ int sqlite3changegroup_output(
/*
** CAPI3REF: Delete A Changegroup Object
*/
-void sqlite3changegroup_delete(sqlite3_changegroup*);
+SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*);
/*
** CAPI3REF: Apply A Changeset To A Database
@@ -9671,7 +10885,7 @@ void sqlite3changegroup_delete(sqlite3_changegroup*);
**
** - The table has the same name as the name recorded in the
** changeset, and
-**
- The table has the same number of columns as recorded in the
+**
- The table has at least as many columns as recorded in the
** changeset, and
**
- The table has primary key columns in the same position as
** recorded in the changeset.
@@ -9716,7 +10930,11 @@ void sqlite3changegroup_delete(sqlite3_changegroup*);
** If a row with matching primary key values is found, but one or more of
** the non-primary key fields contains a value different from the original
** row value stored in the changeset, the conflict-handler function is
-** invoked with [SQLITE_CHANGESET_DATA] as the second argument.
+** invoked with [SQLITE_CHANGESET_DATA] as the second argument. If the
+** database table has more columns than are recorded in the changeset,
+** only the values of those non-primary key fields are compared against
+** the current database contents - any trailing database table columns
+** are ignored.
**
** If no row with matching primary key values is found in the database,
** the conflict-handler function is invoked with [SQLITE_CHANGESET_NOTFOUND]
@@ -9731,7 +10949,9 @@ void sqlite3changegroup_delete(sqlite3_changegroup*);
**
**
- INSERT Changes
-
** For each INSERT change, an attempt is made to insert the new row into
-** the database.
+** the database. If the changeset row contains fewer fields than the
+** database table, the trailing fields are populated with their default
+** values.
**
** If the attempt to insert the row fails because the database already
** contains a row with the same primary key values, the conflict handler
@@ -9749,13 +10969,13 @@ void sqlite3changegroup_delete(sqlite3_changegroup*);
** For each UPDATE change, this function checks if the target database
** contains a row with the same primary key value (or values) as the
** original row values stored in the changeset. If it does, and the values
-** stored in all non-primary key columns also match the values stored in
-** the changeset the row is updated within the target database.
+** stored in all modified non-primary key columns also match the values
+** stored in the changeset the row is updated within the target database.
**
** If a row with matching primary key values is found, but one or more of
-** the non-primary key fields contains a value different from an original
-** row value stored in the changeset, the conflict-handler function is
-** invoked with [SQLITE_CHANGESET_DATA] as the second argument. Since
+** the modified non-primary key fields contains a value different from an
+** original row value stored in the changeset, the conflict-handler function
+** is invoked with [SQLITE_CHANGESET_DATA] as the second argument. Since
** UPDATE changes only contain values for non-primary key fields that are
** to be modified, only those fields need to match the original values to
** avoid the SQLITE_CHANGESET_DATA conflict-handler callback.
@@ -9783,7 +11003,7 @@ void sqlite3changegroup_delete(sqlite3_changegroup*);
** rolled back, restoring the target database to its original state, and an
** SQLite error code returned.
*/
-int sqlite3changeset_apply(
+SQLITE_API int sqlite3changeset_apply(
sqlite3 *db, /* Apply change to "main" db of this handle */
int nChangeset, /* Size of changeset in bytes */
void *pChangeset, /* Changeset blob */
@@ -9903,12 +11123,12 @@ int sqlite3changeset_apply(
**
**
** Streaming function | Non-streaming equivalent |
-**
---|
sqlite3changeset_apply_str | [sqlite3changeset_apply]
-** |
sqlite3changeset_concat_str | [sqlite3changeset_concat]
-** |
sqlite3changeset_invert_str | [sqlite3changeset_invert]
-** |
sqlite3changeset_start_str | [sqlite3changeset_start]
-** |
sqlite3session_changeset_str | [sqlite3session_changeset]
-** |
sqlite3session_patchset_str | [sqlite3session_patchset]
+** |
sqlite3changeset_apply_strm | [sqlite3changeset_apply]
+** |
sqlite3changeset_concat_strm | [sqlite3changeset_concat]
+** |
sqlite3changeset_invert_strm | [sqlite3changeset_invert]
+** |
sqlite3changeset_start_strm | [sqlite3changeset_start]
+** |
sqlite3session_changeset_strm | [sqlite3session_changeset]
+** |
sqlite3session_patchset_strm | [sqlite3session_patchset]
** |
**
** Non-streaming functions that accept changesets (or patchsets) as input
@@ -9984,7 +11204,7 @@ int sqlite3changeset_apply(
** parameter set to a value less than or equal to zero. Other than this,
** no guarantees are made as to the size of the chunks of data returned.
*/
-int sqlite3changeset_apply_strm(
+SQLITE_API int sqlite3changeset_apply_strm(
sqlite3 *db, /* Apply change to "main" db of this handle */
int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */
void *pIn, /* First arg for xInput */
@@ -9999,7 +11219,7 @@ int sqlite3changeset_apply_strm(
),
void *pCtx /* First argument passed to xConflict */
);
-int sqlite3changeset_concat_strm(
+SQLITE_API int sqlite3changeset_concat_strm(
int (*xInputA)(void *pIn, void *pData, int *pnData),
void *pInA,
int (*xInputB)(void *pIn, void *pData, int *pnData),
@@ -10007,32 +11227,32 @@ int sqlite3changeset_concat_strm(
int (*xOutput)(void *pOut, const void *pData, int nData),
void *pOut
);
-int sqlite3changeset_invert_strm(
+SQLITE_API int sqlite3changeset_invert_strm(
int (*xInput)(void *pIn, void *pData, int *pnData),
void *pIn,
int (*xOutput)(void *pOut, const void *pData, int nData),
void *pOut
);
-int sqlite3changeset_start_strm(
+SQLITE_API int sqlite3changeset_start_strm(
sqlite3_changeset_iter **pp,
int (*xInput)(void *pIn, void *pData, int *pnData),
void *pIn
);
-int sqlite3session_changeset_strm(
+SQLITE_API int sqlite3session_changeset_strm(
sqlite3_session *pSession,
int (*xOutput)(void *pOut, const void *pData, int nData),
void *pOut
);
-int sqlite3session_patchset_strm(
+SQLITE_API int sqlite3session_patchset_strm(
sqlite3_session *pSession,
int (*xOutput)(void *pOut, const void *pData, int nData),
void *pOut
);
-int sqlite3changegroup_add_strm(sqlite3_changegroup*,
+SQLITE_API int sqlite3changegroup_add_strm(sqlite3_changegroup*,
int (*xInput)(void *pIn, void *pData, int *pnData),
void *pIn
);
-int sqlite3changegroup_output_strm(sqlite3_changegroup*,
+SQLITE_API int sqlite3changegroup_output_strm(sqlite3_changegroup*,
int (*xOutput)(void *pOut, const void *pData, int nData),
void *pOut
);
@@ -10637,8 +11857,9 @@ struct fts5_api {
** Include the configuration header output by 'configure' if we're using the
** autoconf-based build
*/
-#ifdef _HAVE_SQLITE_CONFIG_H
-#include "config.h"
+#if defined(_HAVE_SQLITE_CONFIG_H) && !defined(SQLITECONFIG_H)
+/* #include "config.h" */
+#define SQLITECONFIG_H 1
#endif
/************** Include sqliteLimit.h in the middle of sqliteInt.h ***********/
@@ -10732,7 +11953,7 @@ struct fts5_api {
** Not currently enforced.
*/
#ifndef SQLITE_MAX_VDBE_OP
-# define SQLITE_MAX_VDBE_OP 25000
+# define SQLITE_MAX_VDBE_OP 250000000
#endif
/*
@@ -10930,6 +12151,7 @@ struct fts5_api {
# include
# pragma intrinsic(_byteswap_ushort)
# pragma intrinsic(_byteswap_ulong)
+# pragma intrinsic(_byteswap_uint64)
# pragma intrinsic(_ReadWriteBarrier)
# else
# include
@@ -10947,6 +12169,11 @@ struct fts5_api {
**
** Older versions of SQLite used an optional THREADSAFE macro.
** We support that for legacy.
+**
+** To ensure that the correct value of "THREADSAFE" is reported when querying
+** for compile-time options at runtime (e.g. "PRAGMA compile_options"), this
+** logic is partially replicated in ctime.c. If it is updated here, it should
+** also be updated there.
*/
#if !defined(SQLITE_THREADSAFE)
# if defined(THREADSAFE)
@@ -11121,6 +12348,21 @@ SQLITE_PRIVATE void sqlite3Coverage(int);
# define NEVER(X) (X)
#endif
+/*
+** Some conditionals are optimizations only. In other words, if the
+** conditionals are replaced with a constant 1 (true) or 0 (false) then
+** the correct answer is still obtained, though perhaps not as quickly.
+**
+** The following macros mark these optimizations conditionals.
+*/
+#if defined(SQLITE_MUTATION_TEST)
+# define OK_IF_ALWAYS_TRUE(X) (1)
+# define OK_IF_ALWAYS_FALSE(X) (0)
+#else
+# define OK_IF_ALWAYS_TRUE(X) (X)
+# define OK_IF_ALWAYS_FALSE(X) (X)
+#endif
+
/*
** Some malloc failures are only possible if SQLITE_TEST_REALLOC_STRESS is
** defined. We need to defend against those failures when testing with
@@ -11315,76 +12557,76 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
#define TK_AS 24
#define TK_WITHOUT 25
#define TK_COMMA 26
-#define TK_OR 27
-#define TK_AND 28
-#define TK_IS 29
-#define TK_MATCH 30
-#define TK_LIKE_KW 31
-#define TK_BETWEEN 32
-#define TK_IN 33
-#define TK_ISNULL 34
-#define TK_NOTNULL 35
-#define TK_NE 36
-#define TK_EQ 37
-#define TK_GT 38
-#define TK_LE 39
-#define TK_LT 40
-#define TK_GE 41
-#define TK_ESCAPE 42
-#define TK_BITAND 43
-#define TK_BITOR 44
-#define TK_LSHIFT 45
-#define TK_RSHIFT 46
-#define TK_PLUS 47
-#define TK_MINUS 48
-#define TK_STAR 49
-#define TK_SLASH 50
-#define TK_REM 51
-#define TK_CONCAT 52
-#define TK_COLLATE 53
-#define TK_BITNOT 54
-#define TK_ID 55
-#define TK_INDEXED 56
-#define TK_ABORT 57
-#define TK_ACTION 58
-#define TK_AFTER 59
-#define TK_ANALYZE 60
-#define TK_ASC 61
-#define TK_ATTACH 62
-#define TK_BEFORE 63
-#define TK_BY 64
-#define TK_CASCADE 65
-#define TK_CAST 66
-#define TK_COLUMNKW 67
-#define TK_CONFLICT 68
-#define TK_DATABASE 69
-#define TK_DESC 70
-#define TK_DETACH 71
-#define TK_EACH 72
-#define TK_FAIL 73
-#define TK_FOR 74
-#define TK_IGNORE 75
-#define TK_INITIALLY 76
-#define TK_INSTEAD 77
-#define TK_NO 78
-#define TK_KEY 79
-#define TK_OF 80
-#define TK_OFFSET 81
-#define TK_PRAGMA 82
-#define TK_RAISE 83
-#define TK_RECURSIVE 84
-#define TK_REPLACE 85
-#define TK_RESTRICT 86
-#define TK_ROW 87
-#define TK_TRIGGER 88
-#define TK_VACUUM 89
-#define TK_VIEW 90
-#define TK_VIRTUAL 91
-#define TK_WITH 92
-#define TK_REINDEX 93
-#define TK_RENAME 94
-#define TK_CTIME_KW 95
-#define TK_ANY 96
+#define TK_ABORT 27
+#define TK_ACTION 28
+#define TK_AFTER 29
+#define TK_ANALYZE 30
+#define TK_ASC 31
+#define TK_ATTACH 32
+#define TK_BEFORE 33
+#define TK_BY 34
+#define TK_CASCADE 35
+#define TK_CAST 36
+#define TK_CONFLICT 37
+#define TK_DATABASE 38
+#define TK_DESC 39
+#define TK_DETACH 40
+#define TK_EACH 41
+#define TK_FAIL 42
+#define TK_OR 43
+#define TK_AND 44
+#define TK_IS 45
+#define TK_MATCH 46
+#define TK_LIKE_KW 47
+#define TK_BETWEEN 48
+#define TK_IN 49
+#define TK_ISNULL 50
+#define TK_NOTNULL 51
+#define TK_NE 52
+#define TK_EQ 53
+#define TK_GT 54
+#define TK_LE 55
+#define TK_LT 56
+#define TK_GE 57
+#define TK_ESCAPE 58
+#define TK_ID 59
+#define TK_COLUMNKW 60
+#define TK_FOR 61
+#define TK_IGNORE 62
+#define TK_INITIALLY 63
+#define TK_INSTEAD 64
+#define TK_NO 65
+#define TK_KEY 66
+#define TK_OF 67
+#define TK_OFFSET 68
+#define TK_PRAGMA 69
+#define TK_RAISE 70
+#define TK_RECURSIVE 71
+#define TK_REPLACE 72
+#define TK_RESTRICT 73
+#define TK_ROW 74
+#define TK_TRIGGER 75
+#define TK_VACUUM 76
+#define TK_VIEW 77
+#define TK_VIRTUAL 78
+#define TK_WITH 79
+#define TK_REINDEX 80
+#define TK_RENAME 81
+#define TK_CTIME_KW 82
+#define TK_ANY 83
+#define TK_BITAND 84
+#define TK_BITOR 85
+#define TK_LSHIFT 86
+#define TK_RSHIFT 87
+#define TK_PLUS 88
+#define TK_MINUS 89
+#define TK_STAR 90
+#define TK_SLASH 91
+#define TK_REM 92
+#define TK_CONCAT 93
+#define TK_COLLATE 94
+#define TK_BITNOT 95
+#define TK_INDEXED 96
#define TK_STRING 97
#define TK_JOIN_KW 98
#define TK_CONSTRAINT 99
@@ -11431,27 +12673,23 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
#define TK_INDEX 140
#define TK_ALTER 141
#define TK_ADD 142
-#define TK_TO_TEXT 143
-#define TK_TO_BLOB 144
-#define TK_TO_NUMERIC 145
-#define TK_TO_INT 146
-#define TK_TO_REAL 147
-#define TK_ISNOT 148
-#define TK_END_OF_FILE 149
-#define TK_UNCLOSED_STRING 150
-#define TK_FUNCTION 151
-#define TK_COLUMN 152
-#define TK_AGG_FUNCTION 153
-#define TK_AGG_COLUMN 154
-#define TK_UMINUS 155
-#define TK_UPLUS 156
-#define TK_REGISTER 157
-#define TK_VECTOR 158
-#define TK_SELECT_COLUMN 159
-#define TK_ASTERISK 160
-#define TK_SPAN 161
-#define TK_SPACE 162
-#define TK_ILLEGAL 163
+#define TK_ISNOT 143
+#define TK_FUNCTION 144
+#define TK_COLUMN 145
+#define TK_AGG_FUNCTION 146
+#define TK_AGG_COLUMN 147
+#define TK_UMINUS 148
+#define TK_UPLUS 149
+#define TK_REGISTER 150
+#define TK_VECTOR 151
+#define TK_SELECT_COLUMN 152
+#define TK_IF_NULL_ROW 153
+#define TK_ASTERISK 154
+#define TK_SPAN 155
+#define TK_END_OF_FILE 156
+#define TK_UNCLOSED_STRING 157
+#define TK_SPACE 158
+#define TK_ILLEGAL 159
/* The token codes above must all fit in 8 bits */
#define TKFLG_MASK 0xff
@@ -11468,6 +12706,18 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
#include
#include
+/*
+** Use a macro to replace memcpy() if compiled with SQLITE_INLINE_MEMCPY.
+** This allows better measurements of where memcpy() is used when running
+** cachegrind. But this macro version of memcpy() is very slow so it
+** should not be used in production. This is a performance measurement
+** hack only.
+*/
+#ifdef SQLITE_INLINE_MEMCPY
+# define memcpy(D,S,N) {char*xxd=(char*)(D);const char*xxs=(const char*)(S);\
+ int xxn=(N);while(xxn-->0)*(xxd++)=*(xxs++);}
+#endif
+
/*
** If compiling for a processor that lacks floating point support,
** substitute integer for floating-point
@@ -11524,7 +12774,6 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
*/
#ifndef SQLITE_TEMP_STORE
# define SQLITE_TEMP_STORE 1
-# define SQLITE_TEMP_STORE_xc 1 /* Exclude from ctime.c */
#endif
/*
@@ -11552,9 +12801,21 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
** pagecaches for each database connection. A positive number is the
** number of pages. A negative number N translations means that a buffer
** of -1024*N bytes is allocated and used for as many pages as it will hold.
+**
+** The default value of "20" was choosen to minimize the run-time of the
+** speedtest1 test program with options: --shrink-memory --reprepare
*/
#ifndef SQLITE_DEFAULT_PCACHE_INITSZ
-# define SQLITE_DEFAULT_PCACHE_INITSZ 100
+# define SQLITE_DEFAULT_PCACHE_INITSZ 20
+#endif
+
+/*
+** The compile-time options SQLITE_MMAP_READWRITE and
+** SQLITE_ENABLE_BATCH_ATOMIC_WRITE are not compatible with one another.
+** You must choose one or the other (or neither) but not both.
+*/
+#if defined(SQLITE_MMAP_READWRITE) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
+#error Cannot use both SQLITE_MMAP_READWRITE and SQLITE_ENABLE_BATCH_ATOMIC_WRITE
#endif
/*
@@ -11729,32 +12990,35 @@ typedef INT16_TYPE LogEst;
**
** For best performance, an attempt is made to guess at the byte-order
** using C-preprocessor macros. If that is unsuccessful, or if
-** -DSQLITE_RUNTIME_BYTEORDER=1 is set, then byte-order is determined
+** -DSQLITE_BYTEORDER=0 is set, then byte-order is determined
** at run-time.
*/
-#if (defined(i386) || defined(__i386__) || defined(_M_IX86) || \
+#ifndef SQLITE_BYTEORDER
+# if defined(i386) || defined(__i386__) || defined(_M_IX86) || \
defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \
defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \
- defined(__arm__)) && !defined(SQLITE_RUNTIME_BYTEORDER)
-# define SQLITE_BYTEORDER 1234
-# define SQLITE_BIGENDIAN 0
-# define SQLITE_LITTLEENDIAN 1
-# define SQLITE_UTF16NATIVE SQLITE_UTF16LE
+ defined(__arm__)
+# define SQLITE_BYTEORDER 1234
+# elif defined(sparc) || defined(__ppc__)
+# define SQLITE_BYTEORDER 4321
+# else
+# define SQLITE_BYTEORDER 0
+# endif
#endif
-#if (defined(sparc) || defined(__ppc__)) \
- && !defined(SQLITE_RUNTIME_BYTEORDER)
-# define SQLITE_BYTEORDER 4321
+#if SQLITE_BYTEORDER==4321
# define SQLITE_BIGENDIAN 1
# define SQLITE_LITTLEENDIAN 0
# define SQLITE_UTF16NATIVE SQLITE_UTF16BE
-#endif
-#if !defined(SQLITE_BYTEORDER)
+#elif SQLITE_BYTEORDER==1234
+# define SQLITE_BIGENDIAN 0
+# define SQLITE_LITTLEENDIAN 1
+# define SQLITE_UTF16NATIVE SQLITE_UTF16LE
+#else
# ifdef SQLITE_AMALGAMATION
const int sqlite3one = 1;
# else
extern const int sqlite3one;
# endif
-# define SQLITE_BYTEORDER 0 /* 0 means "unknown at compile-time" */
# define SQLITE_BIGENDIAN (*(char *)(&sqlite3one)==0)
# define SQLITE_LITTLEENDIAN (*(char *)(&sqlite3one)==1)
# define SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE)
@@ -11819,7 +13083,6 @@ typedef INT16_TYPE LogEst;
# else
# define SQLITE_MAX_MMAP_SIZE 0
# endif
-# define SQLITE_MAX_MMAP_SIZE_xc 1 /* exclude from ctime.c */
#endif
/*
@@ -11829,7 +13092,6 @@ typedef INT16_TYPE LogEst;
*/
#ifndef SQLITE_DEFAULT_MMAP_SIZE
# define SQLITE_DEFAULT_MMAP_SIZE 0
-# define SQLITE_DEFAULT_MMAP_SIZE_xc 1 /* Exclude from ctime.c */
#endif
#if SQLITE_DEFAULT_MMAP_SIZE>SQLITE_MAX_MMAP_SIZE
# undef SQLITE_DEFAULT_MMAP_SIZE
@@ -11854,7 +13116,7 @@ typedef INT16_TYPE LogEst;
** SELECTTRACE_ENABLED will be either 1 or 0 depending on whether or not
** the Select query generator tracing logic is turned on.
*/
-#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_SELECTTRACE)
+#if defined(SQLITE_ENABLE_SELECTTRACE)
# define SELECTTRACE_ENABLED 1
#else
# define SELECTTRACE_ENABLED 0
@@ -11973,7 +13235,6 @@ typedef struct Db Db;
typedef struct Schema Schema;
typedef struct Expr Expr;
typedef struct ExprList ExprList;
-typedef struct ExprSpan ExprSpan;
typedef struct FKey FKey;
typedef struct FuncDestructor FuncDestructor;
typedef struct FuncDef FuncDef;
@@ -12011,6 +13272,14 @@ typedef struct Walker Walker;
typedef struct WhereInfo WhereInfo;
typedef struct With With;
+/* A VList object records a mapping between parameters/variables/wildcards
+** in the SQL statement (such as $abc, @pqr, or :xyz) and the integer
+** variable number associated with that parameter. See the format description
+** on the sqlite3VListAdd() routine for more information. A VList is really
+** just an array of integers.
+*/
+typedef int VList;
+
/*
** Defer sourcing vdbe.h and btree.h until after the "u8" and
** "BusyHandler" typedefs. vdbe.h also requires a few of the opaque
@@ -12250,6 +13519,7 @@ SQLITE_PRIVATE int sqlite3BtreeCursor(
struct KeyInfo*, /* First argument to compare function */
BtCursor *pCursor /* Space to write cursor structure */
);
+SQLITE_PRIVATE BtCursor *sqlite3BtreeFakeValidCursor(void);
SQLITE_PRIVATE int sqlite3BtreeCursorSize(void);
SQLITE_PRIVATE void sqlite3BtreeCursorZero(BtCursor*);
SQLITE_PRIVATE void sqlite3BtreeCursorHintFlags(BtCursor*, unsigned);
@@ -12269,9 +13539,10 @@ SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor*);
SQLITE_PRIVATE int sqlite3BtreeCursorRestore(BtCursor*, int*);
SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor*, u8 flags);
-/* Allowed flags for the 2nd argument to sqlite3BtreeDelete() */
+/* Allowed flags for sqlite3BtreeDelete() and sqlite3BtreeInsert() */
#define BTREE_SAVEPOSITION 0x02 /* Leave cursor pointing at NEXT or PREV */
#define BTREE_AUXDELETE 0x04 /* not the primary delete operation */
+#define BTREE_APPEND 0x08 /* Insert is likely an append */
/* An instance of the BtreePayload object describes the content of a single
** entry in either an index or table btree.
@@ -12295,27 +13566,33 @@ struct BtreePayload {
const void *pKey; /* Key content for indexes. NULL for tables */
sqlite3_int64 nKey; /* Size of pKey for indexes. PRIMARY KEY for tabs */
const void *pData; /* Data for tables. NULL for indexes */
+ sqlite3_value *aMem; /* First of nMem value in the unpacked pKey */
+ u16 nMem; /* Number of aMem[] value. Might be zero */
int nData; /* Size of pData. 0 if none. */
int nZero; /* Extra zero data appended after pData,nData */
};
SQLITE_PRIVATE int sqlite3BtreeInsert(BtCursor*, const BtreePayload *pPayload,
- int bias, int seekResult);
+ int flags, int seekResult);
SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor*, int *pRes);
SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor*, int *pRes);
-SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor*, int *pRes);
+SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor*, int flags);
SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor*);
-SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor*, int *pRes);
+SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor*, int flags);
SQLITE_PRIVATE i64 sqlite3BtreeIntegerKey(BtCursor*);
-SQLITE_PRIVATE int sqlite3BtreeKey(BtCursor*, u32 offset, u32 amt, void*);
+#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
+SQLITE_PRIVATE i64 sqlite3BtreeOffset(BtCursor*);
+#endif
+SQLITE_PRIVATE int sqlite3BtreePayload(BtCursor*, u32 offset, u32 amt, void*);
SQLITE_PRIVATE const void *sqlite3BtreePayloadFetch(BtCursor*, u32 *pAmt);
SQLITE_PRIVATE u32 sqlite3BtreePayloadSize(BtCursor*);
-SQLITE_PRIVATE int sqlite3BtreeData(BtCursor*, u32 offset, u32 amt, void*);
SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*);
SQLITE_PRIVATE struct Pager *sqlite3BtreePager(Btree*);
+SQLITE_PRIVATE i64 sqlite3BtreeRowCountEst(BtCursor*);
#ifndef SQLITE_OMIT_INCRBLOB
+SQLITE_PRIVATE int sqlite3BtreePayloadChecked(BtCursor*, u32 offset, u32 amt, void*);
SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*);
SQLITE_PRIVATE void sqlite3BtreeIncrblobCursor(BtCursor *);
#endif
@@ -12328,6 +13605,7 @@ SQLITE_PRIVATE int sqlite3HeaderSizeBtree(void);
#ifndef NDEBUG
SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor*);
#endif
+SQLITE_PRIVATE int sqlite3BtreeCursorIsValidNN(BtCursor*);
#ifndef SQLITE_OMIT_BTREECOUNT
SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *, i64 *);
@@ -12421,7 +13699,7 @@ typedef struct Vdbe Vdbe;
** The names of the following types declared in vdbeInt.h are required
** for the VdbeOp definition.
*/
-typedef struct Mem Mem;
+typedef struct sqlite3_value Mem;
typedef struct SubProgram SubProgram;
/*
@@ -12432,8 +13710,7 @@ typedef struct SubProgram SubProgram;
struct VdbeOp {
u8 opcode; /* What operation to perform */
signed char p4type; /* One of the P4_xxx constants for p4 */
- u8 notUsed1;
- u8 p5; /* Fifth parameter is an unsigned character */
+ u16 p5; /* Fifth parameter is an unsigned 16-bit integer */
int p1; /* First operand */
int p2; /* Second parameter (often the jump destination) */
int p3; /* The third parameter */
@@ -12455,7 +13732,7 @@ struct VdbeOp {
#ifdef SQLITE_ENABLE_CURSOR_HINTS
Expr *pExpr; /* Used when p4type is P4_EXPR */
#endif
- int (*xAdvance)(BtCursor *, int *);
+ int (*xAdvance)(BtCursor *, int);
} p4;
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
char *zComment; /* Comment to improve readability */
@@ -12479,6 +13756,7 @@ struct SubProgram {
int nOp; /* Elements in aOp[] */
int nMem; /* Number of memory cells required */
int nCsr; /* Number of cursors required */
+ u8 *aOnce; /* Array of OP_Once flags */
void *token; /* id that may be used to recursive triggers */
SubProgram *pNext; /* Next sub-program already visited */
};
@@ -12498,25 +13776,27 @@ typedef struct VdbeOpList VdbeOpList;
/*
** Allowed values of VdbeOp.p4type
*/
-#define P4_NOTUSED 0 /* The P4 parameter is not used */
-#define P4_DYNAMIC (-1) /* Pointer to a string obtained from sqliteMalloc() */
-#define P4_STATIC (-2) /* Pointer to a static string */
-#define P4_COLLSEQ (-4) /* P4 is a pointer to a CollSeq structure */
-#define P4_FUNCDEF (-5) /* P4 is a pointer to a FuncDef structure */
-#define P4_KEYINFO (-6) /* P4 is a pointer to a KeyInfo structure */
-#define P4_EXPR (-7) /* P4 is a pointer to an Expr tree */
-#define P4_MEM (-8) /* P4 is a pointer to a Mem* structure */
-#define P4_TRANSIENT 0 /* P4 is a pointer to a transient string */
-#define P4_VTAB (-10) /* P4 is a pointer to an sqlite3_vtab structure */
-#define P4_MPRINTF (-11) /* P4 is a string obtained from sqlite3_mprintf() */
-#define P4_REAL (-12) /* P4 is a 64-bit floating point value */
-#define P4_INT64 (-13) /* P4 is a 64-bit signed integer */
-#define P4_INT32 (-14) /* P4 is a 32-bit signed integer */
-#define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */
-#define P4_SUBPROGRAM (-18) /* P4 is a pointer to a SubProgram structure */
-#define P4_ADVANCE (-19) /* P4 is a pointer to BtreeNext() or BtreePrev() */
-#define P4_TABLE (-20) /* P4 is a pointer to a Table structure */
-#define P4_FUNCCTX (-21) /* P4 is a pointer to an sqlite3_context object */
+#define P4_NOTUSED 0 /* The P4 parameter is not used */
+#define P4_TRANSIENT 0 /* P4 is a pointer to a transient string */
+#define P4_STATIC (-1) /* Pointer to a static string */
+#define P4_COLLSEQ (-2) /* P4 is a pointer to a CollSeq structure */
+#define P4_INT32 (-3) /* P4 is a 32-bit signed integer */
+#define P4_SUBPROGRAM (-4) /* P4 is a pointer to a SubProgram structure */
+#define P4_ADVANCE (-5) /* P4 is a pointer to BtreeNext() or BtreePrev() */
+#define P4_TABLE (-6) /* P4 is a pointer to a Table structure */
+/* Above do not own any resources. Must free those below */
+#define P4_FREE_IF_LE (-7)
+#define P4_DYNAMIC (-7) /* Pointer to memory from sqliteMalloc() */
+#define P4_FUNCDEF (-8) /* P4 is a pointer to a FuncDef structure */
+#define P4_KEYINFO (-9) /* P4 is a pointer to a KeyInfo structure */
+#define P4_EXPR (-10) /* P4 is a pointer to an Expr tree */
+#define P4_MEM (-11) /* P4 is a pointer to a Mem* structure */
+#define P4_VTAB (-12) /* P4 is a pointer to an sqlite3_vtab structure */
+#define P4_REAL (-13) /* P4 is a 64-bit floating point value */
+#define P4_INT64 (-14) /* P4 is a 64-bit signed integer */
+#define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */
+#define P4_FUNCCTX (-16) /* P4 is a pointer to an sqlite3_context object */
+#define P4_DYNBLOB (-17) /* Pointer to memory from sqliteMalloc() */
/* Error message codes for OP_Halt */
#define P5_ConstraintNotNull 1
@@ -12562,166 +13842,173 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_Savepoint 0
#define OP_AutoCommit 1
#define OP_Transaction 2
-#define OP_SorterNext 3
-#define OP_PrevIfOpen 4
-#define OP_NextIfOpen 5
-#define OP_Prev 6
-#define OP_Next 7
+#define OP_SorterNext 3 /* jump */
+#define OP_PrevIfOpen 4 /* jump */
+#define OP_NextIfOpen 5 /* jump */
+#define OP_Prev 6 /* jump */
+#define OP_Next 7 /* jump */
#define OP_Checkpoint 8
#define OP_JournalMode 9
#define OP_Vacuum 10
-#define OP_VFilter 11 /* synopsis: iplan=r[P3] zplan='P4' */
+#define OP_VFilter 11 /* jump, synopsis: iplan=r[P3] zplan='P4' */
#define OP_VUpdate 12 /* synopsis: data=r[P3@P2] */
-#define OP_Goto 13
-#define OP_Gosub 14
-#define OP_InitCoroutine 15
-#define OP_Yield 16
-#define OP_MustBeInt 17
-#define OP_Jump 18
+#define OP_Goto 13 /* jump */
+#define OP_Gosub 14 /* jump */
+#define OP_InitCoroutine 15 /* jump */
+#define OP_Yield 16 /* jump */
+#define OP_MustBeInt 17 /* jump */
+#define OP_Jump 18 /* jump */
#define OP_Not 19 /* same as TK_NOT, synopsis: r[P2]= !r[P1] */
-#define OP_Once 20
-#define OP_If 21
-#define OP_IfNot 22
-#define OP_SeekLT 23 /* synopsis: key=r[P3@P4] */
-#define OP_SeekLE 24 /* synopsis: key=r[P3@P4] */
-#define OP_SeekGE 25 /* synopsis: key=r[P3@P4] */
-#define OP_SeekGT 26 /* synopsis: key=r[P3@P4] */
-#define OP_Or 27 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */
-#define OP_And 28 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */
-#define OP_NoConflict 29 /* synopsis: key=r[P3@P4] */
-#define OP_NotFound 30 /* synopsis: key=r[P3@P4] */
-#define OP_Found 31 /* synopsis: key=r[P3@P4] */
-#define OP_SeekRowid 32 /* synopsis: intkey=r[P3] */
-#define OP_NotExists 33 /* synopsis: intkey=r[P3] */
-#define OP_IsNull 34 /* same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */
-#define OP_NotNull 35 /* same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */
-#define OP_Ne 36 /* same as TK_NE, synopsis: IF r[P3]!=r[P1] */
-#define OP_Eq 37 /* same as TK_EQ, synopsis: IF r[P3]==r[P1] */
-#define OP_Gt 38 /* same as TK_GT, synopsis: IF r[P3]>r[P1] */
-#define OP_Le 39 /* same as TK_LE, synopsis: IF r[P3]<=r[P1] */
-#define OP_Lt 40 /* same as TK_LT, synopsis: IF r[P3]=r[P1] */
-#define OP_ElseNotEq 42 /* same as TK_ESCAPE */
-#define OP_BitAnd 43 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
-#define OP_BitOr 44 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
-#define OP_ShiftLeft 45 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<>r[P1] */
-#define OP_Add 47 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
-#define OP_Subtract 48 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
-#define OP_Multiply 49 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
-#define OP_Divide 50 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
-#define OP_Remainder 51 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
-#define OP_Concat 52 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
-#define OP_Last 53
-#define OP_BitNot 54 /* same as TK_BITNOT, synopsis: r[P1]= ~r[P1] */
-#define OP_SorterSort 55
-#define OP_Sort 56
-#define OP_Rewind 57
-#define OP_IdxLE 58 /* synopsis: key=r[P3@P4] */
-#define OP_IdxGT 59 /* synopsis: key=r[P3@P4] */
-#define OP_IdxLT 60 /* synopsis: key=r[P3@P4] */
-#define OP_IdxGE 61 /* synopsis: key=r[P3@P4] */
-#define OP_RowSetRead 62 /* synopsis: r[P3]=rowset(P1) */
-#define OP_RowSetTest 63 /* synopsis: if r[P3] in rowset(P1) goto P2 */
-#define OP_Program 64
-#define OP_FkIfZero 65 /* synopsis: if fkctr[P1]==0 goto P2 */
-#define OP_IfPos 66 /* synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */
-#define OP_IfNotZero 67 /* synopsis: if r[P1]!=0 then r[P1]-=P3, goto P2 */
-#define OP_DecrJumpZero 68 /* synopsis: if (--r[P1])==0 goto P2 */
-#define OP_IncrVacuum 69
-#define OP_VNext 70
-#define OP_Init 71 /* synopsis: Start at P2 */
-#define OP_Return 72
-#define OP_EndCoroutine 73
-#define OP_HaltIfNull 74 /* synopsis: if r[P3]=null halt */
-#define OP_Halt 75
-#define OP_Integer 76 /* synopsis: r[P2]=P1 */
-#define OP_Int64 77 /* synopsis: r[P2]=P4 */
-#define OP_String 78 /* synopsis: r[P2]='P4' (len=P1) */
-#define OP_Null 79 /* synopsis: r[P2..P3]=NULL */
-#define OP_SoftNull 80 /* synopsis: r[P1]=NULL */
-#define OP_Blob 81 /* synopsis: r[P2]=P4 (len=P1) */
-#define OP_Variable 82 /* synopsis: r[P2]=parameter(P1,P4) */
-#define OP_Move 83 /* synopsis: r[P2@P3]=r[P1@P3] */
-#define OP_Copy 84 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */
-#define OP_SCopy 85 /* synopsis: r[P2]=r[P1] */
-#define OP_IntCopy 86 /* synopsis: r[P2]=r[P1] */
-#define OP_ResultRow 87 /* synopsis: output=r[P1@P2] */
-#define OP_CollSeq 88
-#define OP_Function0 89 /* synopsis: r[P3]=func(r[P2@P5]) */
-#define OP_Function 90 /* synopsis: r[P3]=func(r[P2@P5]) */
-#define OP_AddImm 91 /* synopsis: r[P1]=r[P1]+P2 */
-#define OP_RealAffinity 92
-#define OP_Cast 93 /* synopsis: affinity(r[P1]) */
-#define OP_Permutation 94
-#define OP_Compare 95 /* synopsis: r[P1@P3] <-> r[P2@P3] */
-#define OP_Column 96 /* synopsis: r[P3]=PX */
+#define OP_Once 20 /* jump */
+#define OP_If 21 /* jump */
+#define OP_IfNot 22 /* jump */
+#define OP_IfNullRow 23 /* jump, synopsis: if P1.nullRow then r[P3]=NULL, goto P2 */
+#define OP_SeekLT 24 /* jump, synopsis: key=r[P3@P4] */
+#define OP_SeekLE 25 /* jump, synopsis: key=r[P3@P4] */
+#define OP_SeekGE 26 /* jump, synopsis: key=r[P3@P4] */
+#define OP_SeekGT 27 /* jump, synopsis: key=r[P3@P4] */
+#define OP_NoConflict 28 /* jump, synopsis: key=r[P3@P4] */
+#define OP_NotFound 29 /* jump, synopsis: key=r[P3@P4] */
+#define OP_Found 30 /* jump, synopsis: key=r[P3@P4] */
+#define OP_SeekRowid 31 /* jump, synopsis: intkey=r[P3] */
+#define OP_NotExists 32 /* jump, synopsis: intkey=r[P3] */
+#define OP_Last 33 /* jump */
+#define OP_IfSmaller 34 /* jump */
+#define OP_SorterSort 35 /* jump */
+#define OP_Sort 36 /* jump */
+#define OP_Rewind 37 /* jump */
+#define OP_IdxLE 38 /* jump, synopsis: key=r[P3@P4] */
+#define OP_IdxGT 39 /* jump, synopsis: key=r[P3@P4] */
+#define OP_IdxLT 40 /* jump, synopsis: key=r[P3@P4] */
+#define OP_IdxGE 41 /* jump, synopsis: key=r[P3@P4] */
+#define OP_RowSetRead 42 /* jump, synopsis: r[P3]=rowset(P1) */
+#define OP_Or 43 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */
+#define OP_And 44 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */
+#define OP_RowSetTest 45 /* jump, synopsis: if r[P3] in rowset(P1) goto P2 */
+#define OP_Program 46 /* jump */
+#define OP_FkIfZero 47 /* jump, synopsis: if fkctr[P1]==0 goto P2 */
+#define OP_IfPos 48 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */
+#define OP_IfNotZero 49 /* jump, synopsis: if r[P1]!=0 then r[P1]--, goto P2 */
+#define OP_IsNull 50 /* jump, same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */
+#define OP_NotNull 51 /* jump, same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */
+#define OP_Ne 52 /* jump, same as TK_NE, synopsis: IF r[P3]!=r[P1] */
+#define OP_Eq 53 /* jump, same as TK_EQ, synopsis: IF r[P3]==r[P1] */
+#define OP_Gt 54 /* jump, same as TK_GT, synopsis: IF r[P3]>r[P1] */
+#define OP_Le 55 /* jump, same as TK_LE, synopsis: IF r[P3]<=r[P1] */
+#define OP_Lt 56 /* jump, same as TK_LT, synopsis: IF r[P3]=r[P1] */
+#define OP_ElseNotEq 58 /* jump, same as TK_ESCAPE */
+#define OP_DecrJumpZero 59 /* jump, synopsis: if (--r[P1])==0 goto P2 */
+#define OP_IncrVacuum 60 /* jump */
+#define OP_VNext 61 /* jump */
+#define OP_Init 62 /* jump, synopsis: Start at P2 */
+#define OP_Return 63
+#define OP_EndCoroutine 64
+#define OP_HaltIfNull 65 /* synopsis: if r[P3]=null halt */
+#define OP_Halt 66
+#define OP_Integer 67 /* synopsis: r[P2]=P1 */
+#define OP_Int64 68 /* synopsis: r[P2]=P4 */
+#define OP_String 69 /* synopsis: r[P2]='P4' (len=P1) */
+#define OP_Null 70 /* synopsis: r[P2..P3]=NULL */
+#define OP_SoftNull 71 /* synopsis: r[P1]=NULL */
+#define OP_Blob 72 /* synopsis: r[P2]=P4 (len=P1) */
+#define OP_Variable 73 /* synopsis: r[P2]=parameter(P1,P4) */
+#define OP_Move 74 /* synopsis: r[P2@P3]=r[P1@P3] */
+#define OP_Copy 75 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */
+#define OP_SCopy 76 /* synopsis: r[P2]=r[P1] */
+#define OP_IntCopy 77 /* synopsis: r[P2]=r[P1] */
+#define OP_ResultRow 78 /* synopsis: output=r[P1@P2] */
+#define OP_CollSeq 79
+#define OP_AddImm 80 /* synopsis: r[P1]=r[P1]+P2 */
+#define OP_RealAffinity 81
+#define OP_Cast 82 /* synopsis: affinity(r[P1]) */
+#define OP_Permutation 83
+#define OP_BitAnd 84 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
+#define OP_BitOr 85 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
+#define OP_ShiftLeft 86 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<>r[P1] */
+#define OP_Add 88 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
+#define OP_Subtract 89 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
+#define OP_Multiply 90 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
+#define OP_Divide 91 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
+#define OP_Remainder 92 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
+#define OP_Concat 93 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
+#define OP_Compare 94 /* synopsis: r[P1@P3] <-> r[P2@P3] */
+#define OP_BitNot 95 /* same as TK_BITNOT, synopsis: r[P1]= ~r[P1] */
+#define OP_Offset 96 /* synopsis: r[P3] = sqlite_offset(P1) */
#define OP_String8 97 /* same as TK_STRING, synopsis: r[P2]='P4' */
-#define OP_Affinity 98 /* synopsis: affinity(r[P1@P2]) */
-#define OP_MakeRecord 99 /* synopsis: r[P3]=mkrec(r[P1@P2]) */
-#define OP_Count 100 /* synopsis: r[P2]=count() */
-#define OP_ReadCookie 101
-#define OP_SetCookie 102
-#define OP_ReopenIdx 103 /* synopsis: root=P2 iDb=P3 */
-#define OP_OpenRead 104 /* synopsis: root=P2 iDb=P3 */
-#define OP_OpenWrite 105 /* synopsis: root=P2 iDb=P3 */
-#define OP_OpenAutoindex 106 /* synopsis: nColumn=P2 */
-#define OP_OpenEphemeral 107 /* synopsis: nColumn=P2 */
-#define OP_SorterOpen 108
-#define OP_SequenceTest 109 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */
-#define OP_OpenPseudo 110 /* synopsis: P3 columns in r[P2] */
-#define OP_Close 111
-#define OP_ColumnsUsed 112
-#define OP_Sequence 113 /* synopsis: r[P2]=cursor[P1].ctr++ */
-#define OP_NewRowid 114 /* synopsis: r[P2]=rowid */
-#define OP_Insert 115 /* synopsis: intkey=r[P3] data=r[P2] */
-#define OP_InsertInt 116 /* synopsis: intkey=P3 data=r[P2] */
-#define OP_Delete 117
-#define OP_ResetCount 118
-#define OP_SorterCompare 119 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */
-#define OP_SorterData 120 /* synopsis: r[P2]=data */
-#define OP_RowKey 121 /* synopsis: r[P2]=key */
-#define OP_RowData 122 /* synopsis: r[P2]=data */
-#define OP_Rowid 123 /* synopsis: r[P2]=rowid */
-#define OP_NullRow 124
-#define OP_SorterInsert 125
-#define OP_IdxInsert 126 /* synopsis: key=r[P2] */
-#define OP_IdxDelete 127 /* synopsis: key=r[P2@P3] */
-#define OP_Seek 128 /* synopsis: Move P3 to P1.rowid */
-#define OP_IdxRowid 129 /* synopsis: r[P2]=rowid */
-#define OP_Destroy 130
-#define OP_Clear 131
+#define OP_Column 98 /* synopsis: r[P3]=PX */
+#define OP_Affinity 99 /* synopsis: affinity(r[P1@P2]) */
+#define OP_MakeRecord 100 /* synopsis: r[P3]=mkrec(r[P1@P2]) */
+#define OP_Count 101 /* synopsis: r[P2]=count() */
+#define OP_ReadCookie 102
+#define OP_SetCookie 103
+#define OP_ReopenIdx 104 /* synopsis: root=P2 iDb=P3 */
+#define OP_OpenRead 105 /* synopsis: root=P2 iDb=P3 */
+#define OP_OpenWrite 106 /* synopsis: root=P2 iDb=P3 */
+#define OP_OpenDup 107
+#define OP_OpenAutoindex 108 /* synopsis: nColumn=P2 */
+#define OP_OpenEphemeral 109 /* synopsis: nColumn=P2 */
+#define OP_SorterOpen 110
+#define OP_SequenceTest 111 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */
+#define OP_OpenPseudo 112 /* synopsis: P3 columns in r[P2] */
+#define OP_Close 113
+#define OP_ColumnsUsed 114
+#define OP_Sequence 115 /* synopsis: r[P2]=cursor[P1].ctr++ */
+#define OP_NewRowid 116 /* synopsis: r[P2]=rowid */
+#define OP_Insert 117 /* synopsis: intkey=r[P3] data=r[P2] */
+#define OP_InsertInt 118 /* synopsis: intkey=P3 data=r[P2] */
+#define OP_Delete 119
+#define OP_ResetCount 120
+#define OP_SorterCompare 121 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */
+#define OP_SorterData 122 /* synopsis: r[P2]=data */
+#define OP_RowData 123 /* synopsis: r[P2]=data */
+#define OP_Rowid 124 /* synopsis: r[P2]=rowid */
+#define OP_NullRow 125
+#define OP_SeekEnd 126
+#define OP_SorterInsert 127 /* synopsis: key=r[P2] */
+#define OP_IdxInsert 128 /* synopsis: key=r[P2] */
+#define OP_IdxDelete 129 /* synopsis: key=r[P2@P3] */
+#define OP_DeferredSeek 130 /* synopsis: Move P3 to P1.rowid if needed */
+#define OP_IdxRowid 131 /* synopsis: r[P2]=rowid */
#define OP_Real 132 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
-#define OP_ResetSorter 133
-#define OP_CreateIndex 134 /* synopsis: r[P2]=root iDb=P1 */
-#define OP_CreateTable 135 /* synopsis: r[P2]=root iDb=P1 */
-#define OP_ParseSchema 136
-#define OP_LoadAnalysis 137
-#define OP_DropTable 138
-#define OP_DropIndex 139
-#define OP_DropTrigger 140
-#define OP_IntegrityCk 141
-#define OP_RowSetAdd 142 /* synopsis: rowset(P1)=r[P2] */
-#define OP_Param 143
-#define OP_FkCounter 144 /* synopsis: fkctr[P1]+=P2 */
-#define OP_MemMax 145 /* synopsis: r[P1]=max(r[P1],r[P2]) */
-#define OP_OffsetLimit 146 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */
-#define OP_AggStep0 147 /* synopsis: accum=r[P3] step(r[P2@P5]) */
-#define OP_AggStep 148 /* synopsis: accum=r[P3] step(r[P2@P5]) */
-#define OP_AggFinal 149 /* synopsis: accum=r[P1] N=P2 */
-#define OP_Expire 150
-#define OP_TableLock 151 /* synopsis: iDb=P1 root=P2 write=P3 */
-#define OP_VBegin 152
-#define OP_VCreate 153
-#define OP_VDestroy 154
-#define OP_VOpen 155
-#define OP_VColumn 156 /* synopsis: r[P3]=vcolumn(P2) */
-#define OP_VRename 157
-#define OP_Pagecount 158
-#define OP_MaxPgcnt 159
-#define OP_CursorHint 160
-#define OP_Noop 161
-#define OP_Explain 162
+#define OP_Destroy 133
+#define OP_Clear 134
+#define OP_ResetSorter 135
+#define OP_CreateBtree 136 /* synopsis: r[P2]=root iDb=P1 flags=P3 */
+#define OP_SqlExec 137
+#define OP_ParseSchema 138
+#define OP_LoadAnalysis 139
+#define OP_DropTable 140
+#define OP_DropIndex 141
+#define OP_DropTrigger 142
+#define OP_IntegrityCk 143
+#define OP_RowSetAdd 144 /* synopsis: rowset(P1)=r[P2] */
+#define OP_Param 145
+#define OP_FkCounter 146 /* synopsis: fkctr[P1]+=P2 */
+#define OP_MemMax 147 /* synopsis: r[P1]=max(r[P1],r[P2]) */
+#define OP_OffsetLimit 148 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */
+#define OP_AggStep0 149 /* synopsis: accum=r[P3] step(r[P2@P5]) */
+#define OP_AggStep 150 /* synopsis: accum=r[P3] step(r[P2@P5]) */
+#define OP_AggFinal 151 /* synopsis: accum=r[P1] N=P2 */
+#define OP_Expire 152
+#define OP_TableLock 153 /* synopsis: iDb=P1 root=P2 write=P3 */
+#define OP_VBegin 154
+#define OP_VCreate 155
+#define OP_VDestroy 156
+#define OP_VOpen 157
+#define OP_VColumn 158 /* synopsis: r[P3]=vcolumn(P2) */
+#define OP_VRename 159
+#define OP_Pagecount 160
+#define OP_MaxPgcnt 161
+#define OP_PureFunc0 162
+#define OP_Function0 163 /* synopsis: r[P3]=func(r[P2@P5]) */
+#define OP_PureFunc 164
+#define OP_Function 165 /* synopsis: r[P3]=func(r[P2@P5]) */
+#define OP_Trace 166
+#define OP_CursorHint 167
+#define OP_Noop 168
+#define OP_Explain 169
/* Properties such as "out2" or "jump" that are specified in
** comments following the "case" for each opcode in the vdbe.c
@@ -12736,25 +14023,26 @@ typedef struct VdbeOpList VdbeOpList;
#define OPFLG_INITIALIZER {\
/* 0 */ 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,\
/* 8 */ 0x00, 0x10, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01,\
-/* 16 */ 0x03, 0x03, 0x01, 0x12, 0x01, 0x03, 0x03, 0x09,\
-/* 24 */ 0x09, 0x09, 0x09, 0x26, 0x26, 0x09, 0x09, 0x09,\
-/* 32 */ 0x09, 0x09, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\
-/* 40 */ 0x0b, 0x0b, 0x01, 0x26, 0x26, 0x26, 0x26, 0x26,\
-/* 48 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x01, 0x12, 0x01,\
-/* 56 */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x23, 0x0b,\
-/* 64 */ 0x01, 0x01, 0x03, 0x03, 0x03, 0x01, 0x01, 0x01,\
-/* 72 */ 0x02, 0x02, 0x08, 0x00, 0x10, 0x10, 0x10, 0x10,\
-/* 80 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00,\
-/* 88 */ 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,\
-/* 96 */ 0x00, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\
+/* 16 */ 0x03, 0x03, 0x01, 0x12, 0x01, 0x03, 0x03, 0x01,\
+/* 24 */ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,\
+/* 32 */ 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\
+/* 40 */ 0x01, 0x01, 0x23, 0x26, 0x26, 0x0b, 0x01, 0x01,\
+/* 48 */ 0x03, 0x03, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\
+/* 56 */ 0x0b, 0x0b, 0x01, 0x03, 0x01, 0x01, 0x01, 0x02,\
+/* 64 */ 0x02, 0x08, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00,\
+/* 72 */ 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\
+/* 80 */ 0x02, 0x02, 0x02, 0x00, 0x26, 0x26, 0x26, 0x26,\
+/* 88 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x00, 0x12,\
+/* 96 */ 0x20, 0x10, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00,\
/* 104 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 112 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 120 */ 0x00, 0x00, 0x00, 0x10, 0x00, 0x04, 0x04, 0x00,\
-/* 128 */ 0x00, 0x10, 0x10, 0x00, 0x10, 0x00, 0x10, 0x10,\
-/* 136 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x10,\
-/* 144 */ 0x00, 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 152 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10,\
-/* 160 */ 0x00, 0x00, 0x00,}
+/* 112 */ 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00,\
+/* 120 */ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x04,\
+/* 128 */ 0x04, 0x00, 0x00, 0x10, 0x10, 0x10, 0x00, 0x00,\
+/* 136 */ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
+/* 144 */ 0x06, 0x10, 0x00, 0x04, 0x1a, 0x00, 0x00, 0x00,\
+/* 152 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
+/* 160 */ 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
+/* 168 */ 0x00, 0x00,}
/* The sqlite3P2Values() routine is able to run faster if it knows
** the value of the largest JUMP opcode. The smaller the maximum
@@ -12762,11 +14050,17 @@ typedef struct VdbeOpList VdbeOpList;
** generated this include file strives to group all JUMP opcodes
** together near the beginning of the list.
*/
-#define SQLITE_MX_JUMP_OPCODE 71 /* Maximum JUMP opcode */
+#define SQLITE_MX_JUMP_OPCODE 62 /* Maximum JUMP opcode */
/************** End of opcodes.h *********************************************/
/************** Continuing where we left off in vdbe.h ***********************/
+/*
+** Additional non-public SQLITE_PREPARE_* flags
+*/
+#define SQLITE_PREPARE_SAVESQL 0x80 /* Preserve SQL text */
+#define SQLITE_PREPARE_MASK 0x0f /* Mask of public flags */
+
/*
** Prototypes for the VDBE interface. See comments on the implementation
** for a description of what each of these routines does.
@@ -12785,8 +14079,10 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int);
SQLITE_PRIVATE void sqlite3VdbeEndCoroutine(Vdbe*,int);
#if defined(SQLITE_DEBUG) && !defined(SQLITE_TEST_REALLOC_STRESS)
SQLITE_PRIVATE void sqlite3VdbeVerifyNoMallocRequired(Vdbe *p, int N);
+SQLITE_PRIVATE void sqlite3VdbeVerifyNoResultRow(Vdbe *p);
#else
# define sqlite3VdbeVerifyNoMallocRequired(A,B)
+# define sqlite3VdbeVerifyNoResultRow(A)
#endif
SQLITE_PRIVATE VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp, int iLineno);
SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*);
@@ -12794,11 +14090,12 @@ SQLITE_PRIVATE void sqlite3VdbeChangeOpcode(Vdbe*, u32 addr, u8);
SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1);
SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2);
SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3);
-SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe*, u8 P5);
+SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe*, u16 P5);
SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe*, int addr);
SQLITE_PRIVATE int sqlite3VdbeChangeToNoop(Vdbe*, int addr);
SQLITE_PRIVATE int sqlite3VdbeDeletePriorOpcode(Vdbe*, u8 op);
SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
+SQLITE_PRIVATE void sqlite3VdbeAppendP4(Vdbe*, void *pP4, int p4type);
SQLITE_PRIVATE void sqlite3VdbeSetP4KeyInfo(Parse*, Index*);
SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int);
SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
@@ -12821,7 +14118,8 @@ SQLITE_PRIVATE void sqlite3VdbeSetNumCols(Vdbe*,int);
SQLITE_PRIVATE int sqlite3VdbeSetColName(Vdbe*, int, int, const char *, void(*)(void*));
SQLITE_PRIVATE void sqlite3VdbeCountChanges(Vdbe*);
SQLITE_PRIVATE sqlite3 *sqlite3VdbeDb(Vdbe*);
-SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe*, const char *z, int n, int);
+SQLITE_PRIVATE u8 sqlite3VdbePrepareFlags(Vdbe*);
+SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe*, const char *z, int n, u8);
SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe*,Vdbe*);
SQLITE_PRIVATE VdbeOp *sqlite3VdbeTakeOpArray(Vdbe*, int*, int*);
SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe*, int, u8);
@@ -12834,7 +14132,7 @@ SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*);
SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(int, const void *, UnpackedRecord *, int);
-SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **);
+SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo*);
typedef int (*RecordCompare)(int,const void*,UnpackedRecord*);
SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*);
@@ -12843,6 +14141,8 @@ SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*);
SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
#endif
+SQLITE_PRIVATE int sqlite3NotPureFunc(sqlite3_context*);
+
/* Use SQLITE_ENABLE_COMMENTS to enable generation of extra comments on
** each VDBE opcode.
**
@@ -13039,7 +14339,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
int,
void(*)(DbPage*)
);
-SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager);
+SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3*);
SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*);
/* Functions used to configure a Pager object. */
@@ -13068,6 +14368,7 @@ SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno);
SQLITE_PRIVATE void sqlite3PagerRef(DbPage*);
SQLITE_PRIVATE void sqlite3PagerUnref(DbPage*);
SQLITE_PRIVATE void sqlite3PagerUnrefNotNull(DbPage*);
+SQLITE_PRIVATE void sqlite3PagerUnrefPageOne(DbPage*);
/* Operations on page references. */
SQLITE_PRIVATE int sqlite3PagerWrite(DbPage*);
@@ -13090,18 +14391,21 @@ SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint);
SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager);
#ifndef SQLITE_OMIT_WAL
-SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int, int*, int*);
+SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, sqlite3*, int, int*, int*);
SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager);
SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager);
SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen);
-SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager);
-SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager);
+SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3*);
+# ifdef SQLITE_DIRECT_OVERFLOW_READ
+SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager, Pgno);
+# endif
# ifdef SQLITE_ENABLE_SNAPSHOT
SQLITE_PRIVATE int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot);
SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot);
+SQLITE_PRIVATE int sqlite3PagerSnapshotRecover(Pager *pPager);
# endif
#else
-# define sqlite3PagerUseWal(x) 0
+# define sqlite3PagerUseWal(x,y) 0
#endif
#ifdef SQLITE_ENABLE_ZIPVFS
@@ -13184,6 +14488,7 @@ struct PgHdr {
sqlite3_pcache_page *pPage; /* Pcache object page handle */
void *pData; /* Page data */
void *pExtra; /* Extra content */
+ PCache *pCache; /* PRIVATE: Cache that owns this page */
PgHdr *pDirty; /* Transient list of dirty sorted by pgno */
Pager *pPager; /* The pager this page is part of */
Pgno pgno; /* Page number for this page */
@@ -13193,14 +14498,15 @@ struct PgHdr {
u16 flags; /* PGHDR flags defined below */
/**********************************************************************
- ** Elements above are public. All that follows is private to pcache.c
- ** and should not be accessed by other modules.
+ ** Elements above, except pCache, are public. All that follow are
+ ** private to pcache.c and should not be accessed by other modules.
+ ** pCache is grouped with the public elements for efficiency.
*/
i16 nRef; /* Number of users of this page */
- PCache *pCache; /* Cache that owns this page */
-
PgHdr *pDirtyNext; /* Next element in list of dirty pages */
PgHdr *pDirtyPrev; /* Previous element in list of dirty pages */
+ /* NB: pDirtyNext and pDirtyPrev are undefined if the
+ ** PgHdr object is not dirty */
};
/* Bit values for PgHdr.flags */
@@ -13582,10 +14888,12 @@ SQLITE_PRIVATE void sqlite3OsFileControlHint(sqlite3_file*,int,void*);
#define SQLITE_FCNTL_DB_UNCHANGED 0xca093fa0
SQLITE_PRIVATE int sqlite3OsSectorSize(sqlite3_file *id);
SQLITE_PRIVATE int sqlite3OsDeviceCharacteristics(sqlite3_file *id);
+#ifndef SQLITE_OMIT_WAL
SQLITE_PRIVATE int sqlite3OsShmMap(sqlite3_file *,int,int,int,void volatile **);
SQLITE_PRIVATE int sqlite3OsShmLock(sqlite3_file *id, int, int, int);
SQLITE_PRIVATE void sqlite3OsShmBarrier(sqlite3_file *id);
SQLITE_PRIVATE int sqlite3OsShmUnmap(sqlite3_file *id, int);
+#endif /* SQLITE_OMIT_WAL */
SQLITE_PRIVATE int sqlite3OsFetch(sqlite3_file *id, i64, int, void **);
SQLITE_PRIVATE int sqlite3OsUnfetch(sqlite3_file *, i64, void *);
@@ -13720,7 +15028,7 @@ SQLITE_PRIVATE void sqlite3OsCloseFree(sqlite3_file *);
** and the one-based values are used internally.
*/
#ifndef SQLITE_DEFAULT_SYNCHRONOUS
-# define SQLITE_DEFAULT_SYNCHRONOUS (PAGER_SYNCHRONOUS_FULL-1)
+# define SQLITE_DEFAULT_SYNCHRONOUS 2
#endif
#ifndef SQLITE_DEFAULT_WAL_SYNCHRONOUS
# define SQLITE_DEFAULT_WAL_SYNCHRONOUS SQLITE_DEFAULT_SYNCHRONOUS
@@ -13794,6 +15102,7 @@ struct Schema {
#define DB_SchemaLoaded 0x0001 /* The schema has been loaded */
#define DB_UnresetViews 0x0002 /* Some views have defined column names */
#define DB_Empty 0x0004 /* The file is empty (length 0 bytes) */
+#define DB_ResetWanted 0x0008 /* Reset the schema when nSchemaLock==0 */
/*
** The number of different kinds of things that can be limited
@@ -13825,9 +15134,9 @@ struct Lookaside {
u32 bDisable; /* Only operate the lookaside when zero */
u16 sz; /* Size of each buffer in bytes */
u8 bMalloced; /* True if pStart obtained from sqlite3_malloc() */
- int nOut; /* Number of buffers currently checked out */
- int mxOut; /* Highwater mark for nOut */
- int anStat[3]; /* 0: hits. 1: size misses. 2: full misses */
+ u32 nSlot; /* Number of lookaside slots allocated */
+ u32 anStat[3]; /* 0: hits. 1: size misses. 2: full misses */
+ LookasideSlot *pInit; /* List of buffers not previously used */
LookasideSlot *pFree; /* List of available buffers */
void *pStart; /* First byte of available memory space */
void *pEnd; /* First byte past end of available space */
@@ -13906,9 +15215,11 @@ struct sqlite3 {
sqlite3_mutex *mutex; /* Connection mutex */
Db *aDb; /* All backends */
int nDb; /* Number of backends currently in use */
- int flags; /* Miscellaneous flags. See below */
+ u32 mDbFlags; /* flags recording internal state */
+ u32 flags; /* flags settable by pragmas. See below */
i64 lastRowid; /* ROWID of most recent insert (see above) */
i64 szMmap; /* Default mmap_size setting */
+ u32 nSchemaLock; /* Do not reset the schema when non-zero */
unsigned int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */
int errCode; /* Most recent error code (SQLITE_*) */
int errMask; /* & result codes with this before returning */
@@ -13925,6 +15236,8 @@ struct sqlite3 {
u8 vtabOnConflict; /* Value to return for s3_vtab_on_conflict() */
u8 isTransactionSavepoint; /* True if the outermost savepoint is a TS */
u8 mTrace; /* zero or more SQLITE_TRACE flags */
+ u8 skipBtreeMutex; /* True if no shared-cache backends */
+ u8 nSqlExec; /* Number of pending OP_SqlExec opcodes */
int nextPagesize; /* Pagesize after VACUUM if >0 */
u32 magic; /* Magic number for detect library misuse */
int nChange; /* Value returned by sqlite3_changes() */
@@ -13989,7 +15302,7 @@ struct sqlite3 {
Hash aModule; /* populated by sqlite3_create_module() */
VtabCtx *pVtabCtx; /* Context for active vtab connect/create */
VTable **aVTrans; /* Virtual tables with open transactions */
- VTable *pDisconnect; /* Disconnect these in next sqlite3_prepare() */
+ VTable *pDisconnect; /* Disconnect these in next sqlite3_prepare() */
#endif
Hash aFunc; /* Hash table of connection functions */
Hash aCollSeq; /* All collating sequences */
@@ -14038,8 +15351,8 @@ struct sqlite3 {
** SQLITE_CkptFullFSync == PAGER_CKPT_FULLFSYNC
** SQLITE_CacheSpill == PAGER_CACHE_SPILL
*/
-#define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */
-#define SQLITE_InternChanges 0x00000002 /* Uncommitted Hash table changes */
+#define SQLITE_WriteSchema 0x00000001 /* OK to update SQLITE_MASTER */
+#define SQLITE_LegacyFileFmt 0x00000002 /* Create new databases in format 1 */
#define SQLITE_FullColNames 0x00000004 /* Show full column names on SELECT */
#define SQLITE_FullFSync 0x00000008 /* Use full fsync on the backend */
#define SQLITE_CkptFullFSync 0x00000010 /* Use full fsync for checkpoint */
@@ -14050,29 +15363,38 @@ struct sqlite3 {
/* the count using a callback. */
#define SQLITE_NullCallback 0x00000100 /* Invoke the callback once if the */
/* result set is empty */
-#define SQLITE_SqlTrace 0x00000200 /* Debug print SQL as it executes */
-#define SQLITE_VdbeListing 0x00000400 /* Debug listings of VDBE programs */
-#define SQLITE_WriteSchema 0x00000800 /* OK to update SQLITE_MASTER */
-#define SQLITE_VdbeAddopTrace 0x00001000 /* Trace sqlite3VdbeAddOp() calls */
-#define SQLITE_IgnoreChecks 0x00002000 /* Do not enforce check constraints */
-#define SQLITE_ReadUncommitted 0x0004000 /* For shared-cache mode */
-#define SQLITE_LegacyFileFmt 0x00008000 /* Create new databases in format 1 */
-#define SQLITE_RecoveryMode 0x00010000 /* Ignore schema errors */
-#define SQLITE_ReverseOrder 0x00020000 /* Reverse unordered SELECTs */
-#define SQLITE_RecTriggers 0x00040000 /* Enable recursive triggers */
-#define SQLITE_ForeignKeys 0x00080000 /* Enforce foreign key constraints */
-#define SQLITE_AutoIndex 0x00100000 /* Enable automatic indexes */
-#define SQLITE_PreferBuiltin 0x00200000 /* Preference to built-in funcs */
-#define SQLITE_LoadExtension 0x00400000 /* Enable load_extension */
-#define SQLITE_LoadExtFunc 0x00800000 /* Enable load_extension() SQL func */
-#define SQLITE_EnableTrigger 0x01000000 /* True to enable triggers */
-#define SQLITE_DeferFKs 0x02000000 /* Defer all FK constraints */
-#define SQLITE_QueryOnly 0x04000000 /* Disable database changes */
-#define SQLITE_VdbeEQP 0x08000000 /* Debug EXPLAIN QUERY PLAN */
-#define SQLITE_Vacuum 0x10000000 /* Currently in a VACUUM */
-#define SQLITE_CellSizeCk 0x20000000 /* Check btree cell sizes on load */
-#define SQLITE_Fts3Tokenizer 0x40000000 /* Enable fts3_tokenizer(2) */
+#define SQLITE_IgnoreChecks 0x00000200 /* Do not enforce check constraints */
+#define SQLITE_ReadUncommit 0x00000400 /* READ UNCOMMITTED in shared-cache */
+#define SQLITE_NoCkptOnClose 0x00000800 /* No checkpoint on close()/DETACH */
+#define SQLITE_ReverseOrder 0x00001000 /* Reverse unordered SELECTs */
+#define SQLITE_RecTriggers 0x00002000 /* Enable recursive triggers */
+#define SQLITE_ForeignKeys 0x00004000 /* Enforce foreign key constraints */
+#define SQLITE_AutoIndex 0x00008000 /* Enable automatic indexes */
+#define SQLITE_LoadExtension 0x00010000 /* Enable load_extension */
+#define SQLITE_LoadExtFunc 0x00020000 /* Enable load_extension() SQL func */
+#define SQLITE_EnableTrigger 0x00040000 /* True to enable triggers */
+#define SQLITE_DeferFKs 0x00080000 /* Defer all FK constraints */
+#define SQLITE_QueryOnly 0x00100000 /* Disable database changes */
+#define SQLITE_CellSizeCk 0x00200000 /* Check btree cell sizes on load */
+#define SQLITE_Fts3Tokenizer 0x00400000 /* Enable fts3_tokenizer(2) */
+#define SQLITE_EnableQPSG 0x00800000 /* Query Planner Stability Guarantee*/
+#define SQLITE_TriggerEQP 0x01000000 /* Show trigger EXPLAIN QUERY PLAN */
+
+/* Flags used only if debugging */
+#ifdef SQLITE_DEBUG
+#define SQLITE_SqlTrace 0x08000000 /* Debug print SQL as it executes */
+#define SQLITE_VdbeListing 0x10000000 /* Debug listings of VDBE programs */
+#define SQLITE_VdbeTrace 0x20000000 /* True to trace VDBE execution */
+#define SQLITE_VdbeAddopTrace 0x40000000 /* Trace sqlite3VdbeAddOp() calls */
+#define SQLITE_VdbeEQP 0x80000000 /* Debug EXPLAIN QUERY PLAN */
+#endif
+/*
+** Allowed values for sqlite3.mDbFlags
+*/
+#define DBFLAG_SchemaChange 0x0001 /* Uncommitted Hash table changes */
+#define DBFLAG_PreferBuiltin 0x0002 /* Preference to built-in funcs */
+#define DBFLAG_Vacuum 0x0004 /* Currently in a VACUUM */
/*
** Bits of the sqlite3.dbOptFlags field that are used by the
@@ -14083,27 +15405,22 @@ struct sqlite3 {
#define SQLITE_ColumnCache 0x0002 /* Column cache */
#define SQLITE_GroupByOrder 0x0004 /* GROUPBY cover of ORDERBY */
#define SQLITE_FactorOutConst 0x0008 /* Constant factoring */
-/* not used 0x0010 // Was: SQLITE_IdxRealAsInt */
-#define SQLITE_DistinctOpt 0x0020 /* DISTINCT using indexes */
-#define SQLITE_CoverIdxScan 0x0040 /* Covering index scans */
-#define SQLITE_OrderByIdxJoin 0x0080 /* ORDER BY of joins via index */
-#define SQLITE_SubqCoroutine 0x0100 /* Evaluate subqueries as coroutines */
-#define SQLITE_Transitive 0x0200 /* Transitive constraints */
-#define SQLITE_OmitNoopJoin 0x0400 /* Omit unused tables in joins */
+#define SQLITE_DistinctOpt 0x0010 /* DISTINCT using indexes */
+#define SQLITE_CoverIdxScan 0x0020 /* Covering index scans */
+#define SQLITE_OrderByIdxJoin 0x0040 /* ORDER BY of joins via index */
+#define SQLITE_Transitive 0x0080 /* Transitive constraints */
+#define SQLITE_OmitNoopJoin 0x0100 /* Omit unused tables in joins */
+#define SQLITE_CountOfView 0x0200 /* The count-of-view optimization */
+#define SQLITE_CursorHints 0x0400 /* Add OP_CursorHint opcodes */
#define SQLITE_Stat34 0x0800 /* Use STAT3 or STAT4 data */
-#define SQLITE_CursorHints 0x2000 /* Add OP_CursorHint opcodes */
+ /* TH3 expects the Stat34 ^^^^^^ value to be 0x0800. Don't change it */
#define SQLITE_AllOpts 0xffff /* All optimizations */
/*
** Macros for testing whether or not optimizations are enabled or disabled.
*/
-#ifndef SQLITE_OMIT_BUILTIN_TEST
#define OptimizationDisabled(db, mask) (((db)->dbOptFlags&(mask))!=0)
#define OptimizationEnabled(db, mask) (((db)->dbOptFlags&(mask))==0)
-#else
-#define OptimizationDisabled(db, mask) 0
-#define OptimizationEnabled(db, mask) 1
-#endif
/*
** Return true if it OK to factor constant expressions into the initialization
@@ -14194,6 +15511,8 @@ struct FuncDestructor {
#define SQLITE_FUNC_MINMAX 0x1000 /* True for min() and max() aggregates */
#define SQLITE_FUNC_SLOCHNG 0x2000 /* "Slow Change". Value constant during a
** single query - might change over time */
+#define SQLITE_FUNC_AFFINITY 0x4000 /* Built-in affinity() function */
+#define SQLITE_FUNC_OFFSET 0x8000 /* Built-in sqlite_offset() function */
/*
** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
@@ -14213,7 +15532,14 @@ struct FuncDestructor {
** Like FUNCTION except it omits the SQLITE_FUNC_CONSTANT flag and
** adds the SQLITE_FUNC_SLOCHNG flag. Used for date & time functions
** and functions like sqlite_version() that can change, but not during
-** a single query.
+** a single query. The iArg is ignored. The user-data is always set
+** to a NULL pointer. The bNC parameter is not used.
+**
+** PURE_DATE(zName, nArg, iArg, bNC, xFunc)
+** Used for "pure" date/time functions, this macro is like DFUNCTION
+** except that it does set the SQLITE_FUNC_CONSTANT flags. iArg is
+** ignored and the user-data for these functions is set to an
+** arbitrary non-NULL pointer. The bNC parameter is not used.
**
** AGGREGATE(zName, nArg, iArg, bNC, xStep, xFinal)
** Used to create an aggregate function definition implemented by
@@ -14236,8 +15562,11 @@ struct FuncDestructor {
{nArg, SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} }
#define DFUNCTION(zName, nArg, iArg, bNC, xFunc) \
- {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
- SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} }
+ {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8, \
+ 0, 0, xFunc, 0, #zName, {0} }
+#define PURE_DATE(zName, nArg, iArg, bNC, xFunc) \
+ {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|SQLITE_FUNC_CONSTANT, \
+ (void*)&sqlite3Config, 0, xFunc, 0, #zName, {0} }
#define FUNCTION2(zName, nArg, iArg, bNC, xFunc, extraFlags) \
{nArg,SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags,\
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} }
@@ -14442,15 +15771,15 @@ struct Table {
ExprList *pCheck; /* All CHECK constraints */
/* ... also used as column name list in a VIEW */
int tnum; /* Root BTree page for this table */
+ u32 nTabRef; /* Number of pointers to this Table */
+ u32 tabFlags; /* Mask of TF_* values */
i16 iPKey; /* If not negative, use aCol[iPKey] as the rowid */
i16 nCol; /* Number of columns in this table */
- u16 nRef; /* Number of pointers to this Table */
LogEst nRowLogEst; /* Estimated rows in table - from sqlite_stat1 table */
LogEst szTabRow; /* Estimated size of each table row in bytes */
#ifdef SQLITE_ENABLE_COSTMULT
LogEst costMult; /* Cost multiplier for using this table */
#endif
- u8 tabFlags; /* Mask of TF_* values */
u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
#ifndef SQLITE_OMIT_ALTERTABLE
int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */
@@ -14474,15 +15803,17 @@ struct Table {
** the TF_OOOHidden attribute would apply in this case. Such tables require
** special handling during INSERT processing.
*/
-#define TF_Readonly 0x01 /* Read-only system table */
-#define TF_Ephemeral 0x02 /* An ephemeral table */
-#define TF_HasPrimaryKey 0x04 /* Table has a primary key */
-#define TF_Autoincrement 0x08 /* Integer primary key is autoincrement */
-#define TF_Virtual 0x10 /* Is a virtual table */
-#define TF_WithoutRowid 0x20 /* No rowid. PRIMARY KEY is the key */
-#define TF_NoVisibleRowid 0x40 /* No user-visible "rowid" column */
-#define TF_OOOHidden 0x80 /* Out-of-Order hidden columns */
-
+#define TF_Readonly 0x0001 /* Read-only system table */
+#define TF_Ephemeral 0x0002 /* An ephemeral table */
+#define TF_HasPrimaryKey 0x0004 /* Table has a primary key */
+#define TF_Autoincrement 0x0008 /* Integer primary key is autoincrement */
+#define TF_HasStat1 0x0010 /* nRowLogEst set from sqlite_stat1 */
+#define TF_WithoutRowid 0x0020 /* No rowid. PRIMARY KEY is the key */
+#define TF_NoVisibleRowid 0x0040 /* No user-visible "rowid" column */
+#define TF_OOOHidden 0x0080 /* Out-of-Order hidden columns */
+#define TF_StatsUsed 0x0100 /* Query planner decisions affected by
+ ** Index.aiRowLogEst[] values */
+#define TF_HasNotNull 0x0200 /* Contains NOT NULL constraints */
/*
** Test to see whether or not a table is a virtual table. This is
@@ -14490,7 +15821,7 @@ struct Table {
** table support is omitted from the build.
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
-# define IsVirtual(X) (((X)->tabFlags & TF_Virtual)!=0)
+# define IsVirtual(X) ((X)->nModuleArg)
#else
# define IsVirtual(X) 0
#endif
@@ -14614,8 +15945,8 @@ struct FKey {
struct KeyInfo {
u32 nRef; /* Number of references to this KeyInfo object */
u8 enc; /* Text encoding - one of the SQLITE_UTF* values */
- u16 nField; /* Number of key columns in the index */
- u16 nXField; /* Number of columns beyond the key columns */
+ u16 nKeyField; /* Number of key columns in the index */
+ u16 nAllField; /* Total columns, including key plus others */
sqlite3 *db; /* The database connection */
u8 *aSortOrder; /* Sort order for each column. */
CollSeq *aColl[1]; /* Collating sequence for each term of the key */
@@ -14662,8 +15993,8 @@ struct UnpackedRecord {
u16 nField; /* Number of entries in apMem[] */
i8 default_rc; /* Comparison result if keys are equal */
u8 errCode; /* Error detected by xRecordCompare (CORRUPT or NOMEM) */
- i8 r1; /* Value to return if (lhs > rhs) */
- i8 r2; /* Value to return if (rhs < lhs) */
+ i8 r1; /* Value to return if (lhs < rhs) */
+ i8 r2; /* Value to return if (lhs > rhs) */
u8 eqSeen; /* True if an equality comparison has been seen */
};
@@ -14725,6 +16056,8 @@ struct Index {
unsigned isResized:1; /* True if resizeIndexObject() has been called */
unsigned isCovering:1; /* True if this is a covering index */
unsigned noSkipScan:1; /* Do not try to use skip-scan if true */
+ unsigned hasStat1:1; /* aiRowLogEst values come from sqlite_stat1 */
+ unsigned bNoQuery:1; /* Do not use this index to optimize queries */
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
int nSample; /* Number of elements in aSample[] */
int nSampleCol; /* Size of IndexSample.anEq[] and so on */
@@ -14946,7 +16279,8 @@ struct Expr {
** TK_COLUMN: the value of p5 for OP_Column
** TK_AGG_FUNCTION: nesting depth */
AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
- Table *pTab; /* Table for TK_COLUMN expressions. */
+ Table *pTab; /* Table for TK_COLUMN expressions. Can be NULL
+ ** for a column of an index on an expression */
};
/*
@@ -14954,8 +16288,8 @@ struct Expr {
*/
#define EP_FromJoin 0x000001 /* Originates in ON/USING clause of outer join */
#define EP_Agg 0x000002 /* Contains one or more aggregate functions */
-#define EP_Resolved 0x000004 /* IDs have been resolved to COLUMNs */
-#define EP_Error 0x000008 /* Expression contains one or more errors */
+#define EP_HasFunc 0x000004 /* Contains one or more functions of any kind */
+ /* 0x000008 // available for use */
#define EP_Distinct 0x000010 /* Aggregate function with DISTINCT keyword */
#define EP_VarSelect 0x000020 /* pSelect is correlated, not constant */
#define EP_DblQuoted 0x000040 /* token.z was originally in "..." */
@@ -14978,9 +16312,10 @@ struct Expr {
#define EP_Leaf 0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */
/*
-** Combinations of two or more EP_* flags
+** The EP_Propagate mask is a set of properties that automatically propagate
+** upwards into parent nodes.
*/
-#define EP_Propagate (EP_Collate|EP_Subquery) /* Propagate these bits up tree */
+#define EP_Propagate (EP_Collate|EP_Subquery|EP_HasFunc)
/*
** These macros can be used to test, set, or clear bits in the
@@ -15035,7 +16370,7 @@ struct Expr {
struct ExprList {
int nExpr; /* Number of expressions on the list */
struct ExprList_item { /* For each expression in the list */
- Expr *pExpr; /* The list of expressions */
+ Expr *pExpr; /* The parse tree for this expression */
char *zName; /* Token associated with this expression */
char *zSpan; /* Original text of the expression */
u8 sortOrder; /* 1 for DESC or 0 for ASC */
@@ -15049,18 +16384,7 @@ struct ExprList {
} x;
int iConstExprReg; /* Register in which Expr value is cached */
} u;
- } *a; /* Alloc a power of two greater or equal to nExpr */
-};
-
-/*
-** An instance of this structure is used by the parser to record both
-** the parse tree for an expression and the span of input text for an
-** expression.
-*/
-struct ExprSpan {
- Expr *pExpr; /* The expression parse tree */
- const char *zStart; /* First character of input text */
- const char *zEnd; /* One character past the end of input text */
+ } a[1]; /* One slot for each expression in the list */
};
/*
@@ -15200,7 +16524,7 @@ struct SrcList {
#define WHERE_SORTBYGROUP 0x0200 /* Support sqlite3WhereIsSorted() */
#define WHERE_SEEK_TABLE 0x0400 /* Do not defer seeks on main table */
#define WHERE_ORDERBY_LIMIT 0x0800 /* ORDERBY+LIMIT on the inner loop */
- /* 0x1000 not currently used */
+#define WHERE_SEEK_UNIQ_TABLE 0x1000 /* Do not defer seeks if unique */
/* 0x2000 not currently used */
#define WHERE_USE_LIMIT 0x4000 /* Use the LIMIT in cost estimates */
/* 0x8000 not currently used */
@@ -15260,6 +16584,7 @@ struct NameContext {
#define NC_IdxExpr 0x0020 /* True if resolving columns of CREATE INDEX */
#define NC_VarSelect 0x0040 /* A correlated subquery has been seen */
#define NC_MinMaxAgg 0x1000 /* min/max aggregates seen. See note above */
+#define NC_Complex 0x2000 /* True if a function or subquery seen */
/*
** An instance of the following structure contains all information
@@ -15299,7 +16624,6 @@ struct Select {
Select *pPrior; /* Prior select in a compound select statement */
Select *pNext; /* Next select to the left in a compound */
Expr *pLimit; /* LIMIT expression. NULL means not used. */
- Expr *pOffset; /* OFFSET expression. NULL means not used. */
With *pWith; /* WITH clause attached to this select. Or NULL. */
};
@@ -15330,6 +16654,7 @@ struct Select {
#define SF_MaybeConvert 0x08000 /* Need convertCompoundSelectToSubquery() */
#define SF_Converted 0x10000 /* By convertCompoundSelectToSubquery() */
#define SF_IncludeHidden 0x20000 /* Include hidden columns in output */
+#define SF_ComplexResult 0x40000 /* Result set contains subquery or function */
/*
@@ -15421,10 +16746,10 @@ struct Select {
*/
struct SelectDest {
u8 eDest; /* How to dispose of the results. On of SRT_* above. */
- char *zAffSdst; /* Affinity used when eDest==SRT_Set */
int iSDParm; /* A parameter used by the eDest disposal method */
int iSdst; /* Base register where results are written */
int nSdst; /* Number of registers allocated */
+ char *zAffSdst; /* Affinity used when eDest==SRT_Set */
ExprList *pOrderBy; /* Key columns for SRT_Queue and SRT_DistQueue */
};
@@ -15534,8 +16859,8 @@ struct Parse {
int nMem; /* Number of memory cells used so far */
int nOpAlloc; /* Number of slots allocated for Vdbe.aOp[] */
int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */
- int ckBase; /* Base register of data during check constraints */
- int iSelfTab; /* Table of an index whose exprs are being coded */
+ int iSelfTab; /* Table associated with an index on expr, or negative
+ ** of the base register during check-constraint eval */
int iCacheLevel; /* ColCache valid when aColCache[].iLevel<=iCacheLevel */
int iCacheCnt; /* Counter used to generate aColCache[].lru values */
int nLabel; /* Number of labels used */
@@ -15558,7 +16883,7 @@ struct Parse {
AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */
Parse *pToplevel; /* Parse structure for main program (or NULL) */
Table *pTriggerTab; /* Table triggers are being coded for */
- int addrCrTab; /* Address of OP_CreateTable opcode on CREATE TABLE */
+ int addrCrTab; /* Address of OP_CreateBtree opcode on CREATE TABLE */
u32 nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */
u32 oldmask; /* Mask of old.* columns referenced */
u32 newmask; /* Mask of new.* columns referenced */
@@ -15593,7 +16918,6 @@ struct Parse {
Token sLastToken; /* The last token parsed */
ynVar nVar; /* Number of '?' variables seen in the SQL so far */
- int nzVar; /* Number of available slots in azVar[] */
u8 iPkSortOrder; /* ASC or DESC for INTEGER PRIMARY KEY */
u8 explain; /* True if the EXPLAIN flag is found on the query */
#ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -15605,7 +16929,7 @@ struct Parse {
int iSelectId; /* ID of current select for EXPLAIN output */
int iNextSelectId; /* Next available select ID for EXPLAIN output */
#endif
- char **azVar; /* Pointers to names of parameters */
+ VList *pVList; /* Mapping between variable names and numbers */
Vdbe *pReprepare; /* VM being reprepared (sqlite3Reprepare()) */
const char *zTail; /* All SQL text past the last semicolon parsed */
Table *pNewTable; /* A table being constructed by CREATE TABLE */
@@ -15662,13 +16986,11 @@ struct AuthContext {
#define OPFLAG_NCHANGE 0x01 /* OP_Insert: Set to update db->nChange */
/* Also used in P2 (not P5) of OP_Delete */
#define OPFLAG_EPHEM 0x01 /* OP_Column: Ephemeral output is ok */
-#define OPFLAG_LASTROWID 0x02 /* Set to update db->lastRowid */
+#define OPFLAG_LASTROWID 0x20 /* Set to update db->lastRowid */
#define OPFLAG_ISUPDATE 0x04 /* This OP_Insert is an sql UPDATE */
#define OPFLAG_APPEND 0x08 /* This is likely to be an append */
#define OPFLAG_USESEEKRESULT 0x10 /* Try to avoid a seek in BtreeInsert() */
-#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
#define OPFLAG_ISNOOP 0x40 /* OP_Delete does pre-update-hook only */
-#endif
#define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */
#define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */
#define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */
@@ -15676,8 +16998,9 @@ struct AuthContext {
#define OPFLAG_FORDELETE 0x08 /* OP_Open should use BTREE_FORDELETE */
#define OPFLAG_P2ISREG 0x10 /* P2 to OP_Open** is a register number */
#define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */
-#define OPFLAG_SAVEPOSITION 0x02 /* OP_Delete: keep cursor position */
+#define OPFLAG_SAVEPOSITION 0x02 /* OP_Delete/Insert: save cursor pos */
#define OPFLAG_AUXDELETE 0x04 /* OP_Delete: index in a DELETE op */
+#define OPFLAG_NOCHNG_MAGIC 0x6d /* OP_MakeRecord: serialtype 10 is ok */
/*
* Each trigger present in the database schema is stored as an instance of
@@ -15765,6 +17088,7 @@ struct TriggerStep {
Expr *pWhere; /* The WHERE clause for DELETE or UPDATE steps */
ExprList *pExprList; /* SET clause for UPDATE. */
IdList *pIdList; /* Column names for INSERT */
+ char *zSpan; /* Original SQL text of this command */
TriggerStep *pNext; /* Next in the link-list */
TriggerStep *pLast; /* Last element in link-list. Valid for 1st elem only */
};
@@ -15790,11 +17114,10 @@ struct DbFixer {
*/
struct StrAccum {
sqlite3 *db; /* Optional database for lookaside. Can be NULL */
- char *zBase; /* A base allocation. Not from malloc. */
char *zText; /* The string collected so far */
- u32 nChar; /* Length of the string so far */
u32 nAlloc; /* Amount of space allocated in zText */
u32 mxAlloc; /* Maximum allowed allocation. 0 for no malloc usage */
+ u32 nChar; /* Length of the string so far */
u8 accError; /* STRACCUM_NOMEM or STRACCUM_TOOBIG */
u8 printfFlags; /* SQLITE_PRINTF flags below */
};
@@ -15829,6 +17152,7 @@ struct Sqlite3Config {
int bFullMutex; /* True to enable full mutexing */
int bOpenUri; /* True to interpret filenames as URIs */
int bUseCis; /* Use covering indices for full-scans */
+ int bSmallMalloc; /* Avoid large memory allocations if true */
int mxStrlen; /* Maximum string length */
int neverCorrupt; /* Database is always well-formed */
int szLookaside; /* Default lookaside buffer size */
@@ -15842,9 +17166,6 @@ struct Sqlite3Config {
int mnReq, mxReq; /* Min and max heap requests sizes */
sqlite3_int64 szMmap; /* mmap() space per open file */
sqlite3_int64 mxMmap; /* Maximum value for szMmap */
- void *pScratch; /* Scratch memory */
- int szScratch; /* Size of each scratch buffer */
- int nScratch; /* Number of scratch buffers */
void *pPage; /* Page cache memory */
int szPage; /* Size of each page in pPage[] */
int nPage; /* Number of pages in pPage[] */
@@ -15873,7 +17194,7 @@ struct Sqlite3Config {
void (*xVdbeBranch)(void*,int iSrcLine,u8 eThis,u8 eMx); /* Callback */
void *pVdbeBranchArg; /* 1st argument */
#endif
-#ifndef SQLITE_OMIT_BUILTIN_TEST
+#ifndef SQLITE_UNTESTABLE
int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */
#endif
int bLocaltimeFault; /* True to fail localtime() calls */
@@ -15909,14 +17230,17 @@ struct Walker {
int walkerDepth; /* Number of subqueries */
u8 eCode; /* A small processing code */
union { /* Extra data for callback */
- NameContext *pNC; /* Naming context */
- int n; /* A counter */
- int iCur; /* A cursor number */
- SrcList *pSrcList; /* FROM clause */
- struct SrcCount *pSrcCount; /* Counting column references */
- struct CCurHint *pCCurHint; /* Used by codeCursorHint() */
- int *aiCol; /* array of column indexes */
- struct IdxCover *pIdxCover; /* Check for index coverage */
+ NameContext *pNC; /* Naming context */
+ int n; /* A counter */
+ int iCur; /* A cursor number */
+ SrcList *pSrcList; /* FROM clause */
+ struct SrcCount *pSrcCount; /* Counting column references */
+ struct CCurHint *pCCurHint; /* Used by codeCursorHint() */
+ int *aiCol; /* array of column indexes */
+ struct IdxCover *pIdxCover; /* Check for index coverage */
+ struct IdxExprTrans *pIdxTrans; /* Convert indexed expr to column */
+ ExprList *pGroupBy; /* GROUP BY clause */
+ struct HavingToWhereCtx *pHavingCtx; /* HAVING to WHERE clause ctx */
} u;
};
@@ -15927,6 +17251,11 @@ SQLITE_PRIVATE int sqlite3WalkSelect(Walker*, Select*);
SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker*, Select*);
SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker*, Select*);
SQLITE_PRIVATE int sqlite3ExprWalkNoop(Walker*, Expr*);
+SQLITE_PRIVATE int sqlite3SelectWalkNoop(Walker*, Select*);
+SQLITE_PRIVATE int sqlite3SelectWalkFail(Walker*, Select*);
+#ifdef SQLITE_DEBUG
+SQLITE_PRIVATE void sqlite3SelectWalkAssert2(Walker*, Select*);
+#endif
/*
** Return code from the parse-tree walking primitives and their
@@ -15979,6 +17308,7 @@ struct TreeView {
** using sqlite3_log(). The routines also provide a convenient place
** to set a debugger breakpoint.
*/
+SQLITE_PRIVATE int sqlite3ReportError(int iErr, int lineno, const char *zType);
SQLITE_PRIVATE int sqlite3CorruptError(int);
SQLITE_PRIVATE int sqlite3MisuseError(int);
SQLITE_PRIVATE int sqlite3CantopenError(int);
@@ -15988,11 +17318,14 @@ SQLITE_PRIVATE int sqlite3CantopenError(int);
#ifdef SQLITE_DEBUG
SQLITE_PRIVATE int sqlite3NomemError(int);
SQLITE_PRIVATE int sqlite3IoerrnomemError(int);
+SQLITE_PRIVATE int sqlite3CorruptPgnoError(int,Pgno);
# define SQLITE_NOMEM_BKPT sqlite3NomemError(__LINE__)
# define SQLITE_IOERR_NOMEM_BKPT sqlite3IoerrnomemError(__LINE__)
+# define SQLITE_CORRUPT_PGNO(P) sqlite3CorruptPgnoError(__LINE__,(P))
#else
# define SQLITE_NOMEM_BKPT SQLITE_NOMEM
# define SQLITE_IOERR_NOMEM_BKPT SQLITE_IOERR_NOMEM
+# define SQLITE_CORRUPT_PGNO(P) sqlite3CorruptError(__LINE__)
#endif
/*
@@ -16066,18 +17399,18 @@ SQLITE_PRIVATE void *sqlite3DbMallocRaw(sqlite3*, u64);
SQLITE_PRIVATE void *sqlite3DbMallocRawNN(sqlite3*, u64);
SQLITE_PRIVATE char *sqlite3DbStrDup(sqlite3*,const char*);
SQLITE_PRIVATE char *sqlite3DbStrNDup(sqlite3*,const char*, u64);
+SQLITE_PRIVATE char *sqlite3DbSpanDup(sqlite3*,const char*,const char*);
SQLITE_PRIVATE void *sqlite3Realloc(void*, u64);
SQLITE_PRIVATE void *sqlite3DbReallocOrFree(sqlite3 *, void *, u64);
SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *, void *, u64);
SQLITE_PRIVATE void sqlite3DbFree(sqlite3*, void*);
+SQLITE_PRIVATE void sqlite3DbFreeNN(sqlite3*, void*);
SQLITE_PRIVATE int sqlite3MallocSize(void*);
SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3*, void*);
-SQLITE_PRIVATE void *sqlite3ScratchMalloc(int);
-SQLITE_PRIVATE void sqlite3ScratchFree(void*);
SQLITE_PRIVATE void *sqlite3PageMalloc(int);
SQLITE_PRIVATE void sqlite3PageFree(void*);
SQLITE_PRIVATE void sqlite3MemSetDefault(void);
-#ifndef SQLITE_OMIT_BUILTIN_TEST
+#ifndef SQLITE_UNTESTABLE
SQLITE_PRIVATE void sqlite3BenignMallocHooks(void (*)(void), void (*)(void));
#endif
SQLITE_PRIVATE int sqlite3HeapNearlyFull(void);
@@ -16129,11 +17462,18 @@ SQLITE_PRIVATE sqlite3_int64 sqlite3StatusValue(int);
SQLITE_PRIVATE void sqlite3StatusUp(int, int);
SQLITE_PRIVATE void sqlite3StatusDown(int, int);
SQLITE_PRIVATE void sqlite3StatusHighwater(int, int);
+SQLITE_PRIVATE int sqlite3LookasideUsed(sqlite3*,int*);
/* Access to mutexes used by sqlite3_status() */
SQLITE_PRIVATE sqlite3_mutex *sqlite3Pcache1Mutex(void);
SQLITE_PRIVATE sqlite3_mutex *sqlite3MallocMutex(void);
+#if defined(SQLITE_ENABLE_MULTITHREADED_CHECKS) && !defined(SQLITE_MUTEX_OMIT)
+SQLITE_PRIVATE void sqlite3MutexWarnOnContention(sqlite3_mutex*);
+#else
+# define sqlite3MutexWarnOnContention(x)
+#endif
+
#ifndef SQLITE_OMIT_FLOATING_POINT
SQLITE_PRIVATE int sqlite3IsNaN(double);
#else
@@ -16188,7 +17528,7 @@ SQLITE_PRIVATE int sqlite3NoTempsInRange(Parse*,int,int);
SQLITE_PRIVATE Expr *sqlite3ExprAlloc(sqlite3*,int,const Token*,int);
SQLITE_PRIVATE Expr *sqlite3Expr(sqlite3*,int,const char*);
SQLITE_PRIVATE void sqlite3ExprAttachSubtrees(sqlite3*,Expr*,Expr*,Expr*);
-SQLITE_PRIVATE Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*, const Token*);
+SQLITE_PRIVATE Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*);
SQLITE_PRIVATE void sqlite3PExprAddSelect(Parse*, Expr*, Select*);
SQLITE_PRIVATE Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*);
SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*);
@@ -16198,12 +17538,15 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*);
SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList*,int);
SQLITE_PRIVATE void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
-SQLITE_PRIVATE void sqlite3ExprListSetSpan(Parse*,ExprList*,ExprSpan*);
+SQLITE_PRIVATE void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*);
SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3*, ExprList*);
SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList*);
SQLITE_PRIVATE int sqlite3Init(sqlite3*, char**);
SQLITE_PRIVATE int sqlite3InitCallback(void*, int, char**, char**);
SQLITE_PRIVATE void sqlite3Pragma(Parse*,Token*,Token*,Token*,int);
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+SQLITE_PRIVATE Module *sqlite3PragmaVtabRegister(sqlite3*,const char *zName);
+#endif
SQLITE_PRIVATE void sqlite3ResetAllSchemasOfConnection(sqlite3*);
SQLITE_PRIVATE void sqlite3ResetOneSchema(sqlite3*,int);
SQLITE_PRIVATE void sqlite3CollapseDatabaseArray(sqlite3*);
@@ -16225,14 +17568,14 @@ SQLITE_PRIVATE void sqlite3AddColumn(Parse*,Token*,Token*);
SQLITE_PRIVATE void sqlite3AddNotNull(Parse*, int);
SQLITE_PRIVATE void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int);
SQLITE_PRIVATE void sqlite3AddCheckConstraint(Parse*, Expr*);
-SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse*,ExprSpan*);
+SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse*,Expr*,const char*,const char*);
SQLITE_PRIVATE void sqlite3AddCollateType(Parse*, Token*);
SQLITE_PRIVATE void sqlite3EndTable(Parse*,Token*,Token*,u8,Select*);
SQLITE_PRIVATE int sqlite3ParseUri(const char*,const char*,unsigned int*,
sqlite3_vfs**,char**,char **);
SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3*,const char*);
-#ifdef SQLITE_OMIT_BUILTIN_TEST
+#ifdef SQLITE_UNTESTABLE
# define sqlite3FaultSim(X) SQLITE_OK
#else
SQLITE_PRIVATE int sqlite3FaultSim(int);
@@ -16245,7 +17588,7 @@ SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec*, u32);
SQLITE_PRIVATE void sqlite3BitvecClear(Bitvec*, u32, void*);
SQLITE_PRIVATE void sqlite3BitvecDestroy(Bitvec*);
SQLITE_PRIVATE u32 sqlite3BitvecSize(Bitvec*);
-#ifndef SQLITE_OMIT_BUILTIN_TEST
+#ifndef SQLITE_UNTESTABLE
SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int,int*);
#endif
@@ -16297,16 +17640,16 @@ SQLITE_PRIVATE void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,i
SQLITE_PRIVATE void sqlite3DropIndex(Parse*, SrcList*, int);
SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*);
SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
- Expr*,ExprList*,u32,Expr*,Expr*);
+ Expr*,ExprList*,u32,Expr*);
SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3*, Select*);
SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse*, SrcList*);
SQLITE_PRIVATE int sqlite3IsReadOnly(Parse*, Table*, int);
SQLITE_PRIVATE void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
-SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,Expr*,char*);
+SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,char*);
#endif
-SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
-SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
+SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*, ExprList*, Expr*);
+SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*,Expr*,int,ExprList*,Expr*);
SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int);
SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*);
SQLITE_PRIVATE LogEst sqlite3WhereOutputRowCount(WhereInfo*);
@@ -16334,7 +17677,7 @@ SQLITE_PRIVATE void sqlite3ExprCacheAffinityChange(Parse*, int, int);
SQLITE_PRIVATE void sqlite3ExprCode(Parse*, Expr*, int);
SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, Expr*, int);
SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse*, Expr*, int);
-SQLITE_PRIVATE void sqlite3ExprCodeAtInit(Parse*, Expr*, int, u8);
+SQLITE_PRIVATE int sqlite3ExprCodeAtInit(Parse*, Expr*, int);
SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse*, Expr*, int*);
SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse*, Expr*, int);
SQLITE_PRIVATE void sqlite3ExprCodeAndCache(Parse*, Expr*, int);
@@ -16342,6 +17685,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeExprList(Parse*, ExprList*, int, int, u8);
#define SQLITE_ECEL_DUP 0x01 /* Deep, not shallow copies */
#define SQLITE_ECEL_FACTOR 0x02 /* Factor out constant terms */
#define SQLITE_ECEL_REF 0x04 /* Use ExprList.u.x.iOrderByCol */
+#define SQLITE_ECEL_OMITREF 0x08 /* Omit if ExprList.u.x.iOrderByCol */
SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse*, Expr*, int, int);
SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse*, Expr*, int, int);
SQLITE_PRIVATE void sqlite3ExprIfFalseDup(Parse*, Expr*, int, int);
@@ -16356,15 +17700,16 @@ SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*);
SQLITE_PRIVATE void sqlite3Vacuum(Parse*,Token*);
SQLITE_PRIVATE int sqlite3RunVacuum(char**, sqlite3*, int);
SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3*, Token*);
-SQLITE_PRIVATE int sqlite3ExprCompare(Expr*, Expr*, int);
+SQLITE_PRIVATE int sqlite3ExprCompare(Parse*,Expr*, Expr*, int);
+SQLITE_PRIVATE int sqlite3ExprCompareSkip(Expr*, Expr*, int);
SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList*, ExprList*, int);
-SQLITE_PRIVATE int sqlite3ExprImpliesExpr(Expr*, Expr*, int);
+SQLITE_PRIVATE int sqlite3ExprImpliesExpr(Parse*,Expr*, Expr*, int);
SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
SQLITE_PRIVATE int sqlite3ExprCoveredByIndex(Expr*, int iCur, Index *pIdx);
SQLITE_PRIVATE int sqlite3FunctionUsesThisSrc(Expr*, SrcList*);
SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse*);
-#ifndef SQLITE_OMIT_BUILTIN_TEST
+#ifndef SQLITE_UNTESTABLE
SQLITE_PRIVATE void sqlite3PrngSaveState(void);
SQLITE_PRIVATE void sqlite3PrngRestoreState(void);
#endif
@@ -16372,14 +17717,14 @@ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3*,int);
SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse*, int);
SQLITE_PRIVATE void sqlite3CodeVerifyNamedSchema(Parse*, const char *zDb);
SQLITE_PRIVATE void sqlite3BeginTransaction(Parse*, int);
-SQLITE_PRIVATE void sqlite3CommitTransaction(Parse*);
-SQLITE_PRIVATE void sqlite3RollbackTransaction(Parse*);
+SQLITE_PRIVATE void sqlite3EndTransaction(Parse*,int);
SQLITE_PRIVATE void sqlite3Savepoint(Parse*, int, Token*);
SQLITE_PRIVATE void sqlite3CloseSavepoints(sqlite3 *);
SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3*);
SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr*);
SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr*);
SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr*, u8);
+SQLITE_PRIVATE int sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*);
SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr*,int);
#ifdef SQLITE_ENABLE_CURSOR_HINTS
SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr*);
@@ -16395,6 +17740,11 @@ SQLITE_PRIVATE int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,I
SQLITE_PRIVATE void sqlite3ResolvePartIdxLabel(Parse*,int);
SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int,
u8,u8,int,int*,int*);
+#ifdef SQLITE_ENABLE_NULL_TRIM
+SQLITE_PRIVATE void sqlite3SetMakeRecordP5(Vdbe*,Table*);
+#else
+# define sqlite3SetMakeRecordP5(A,B)
+#endif
SQLITE_PRIVATE void sqlite3CompleteInsertion(Parse*,Table*,int,int,int,int*,int,int,int);
SQLITE_PRIVATE int sqlite3OpenTableAndIndices(Parse*, Table*, int, u8, int, u8*, int*, int*);
SQLITE_PRIVATE void sqlite3BeginWriteOperation(Parse*, int, int);
@@ -16423,7 +17773,7 @@ SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3*);
SQLITE_PRIVATE void sqlite3ChangeCookie(Parse*, int);
#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
-SQLITE_PRIVATE void sqlite3MaterializeView(Parse*, Table*, Expr*, int);
+SQLITE_PRIVATE void sqlite3MaterializeView(Parse*, Table*, Expr*, ExprList*,Expr*,int);
#endif
#ifndef SQLITE_OMIT_TRIGGER
@@ -16439,11 +17789,14 @@ SQLITE_PRIVATE void sqlite3CodeRowTrigger(Parse*, Trigger *, int, ExprList*, i
SQLITE_PRIVATE void sqlite3CodeRowTriggerDirect(Parse *, Trigger *, Table *, int, int, int);
void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*);
SQLITE_PRIVATE void sqlite3DeleteTriggerStep(sqlite3*, TriggerStep*);
-SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*);
+SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*,
+ const char*,const char*);
SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep(sqlite3*,Token*, IdList*,
- Select*,u8);
-SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(sqlite3*,Token*,ExprList*, Expr*, u8);
-SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(sqlite3*,Token*, Expr*);
+ Select*,u8,const char*,const char*);
+SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(sqlite3*,Token*,ExprList*, Expr*, u8,
+ const char*,const char*);
+SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(sqlite3*,Token*, Expr*,
+ const char*,const char*);
SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3*, Trigger*);
SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*);
SQLITE_PRIVATE u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Table*,int);
@@ -16488,7 +17841,9 @@ SQLITE_PRIVATE int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
SQLITE_PRIVATE int sqlite3AtoF(const char *z, double*, int, u8);
SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*);
SQLITE_PRIVATE int sqlite3Atoi(const char*);
+#ifndef SQLITE_OMIT_UTF16
SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar);
+#endif
SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte);
SQLITE_PRIVATE u32 sqlite3Utf8Read(const u8**);
SQLITE_PRIVATE LogEst sqlite3LogEst(u64);
@@ -16501,6 +17856,9 @@ SQLITE_PRIVATE LogEst sqlite3LogEstFromDouble(double);
defined(SQLITE_EXPLAIN_ESTIMATED_ROWS)
SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst);
#endif
+SQLITE_PRIVATE VList *sqlite3VListAdd(sqlite3*,VList*,const char*,int,int);
+SQLITE_PRIVATE const char *sqlite3VListNumToName(VList*,int);
+SQLITE_PRIVATE int sqlite3VListNameToNum(VList*,const char*,int);
/*
** Routines to read and write variable-length integers. These used to
@@ -16550,6 +17908,8 @@ SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse);
SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
+SQLITE_PRIVATE CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, Expr *pExpr);
+SQLITE_PRIVATE int sqlite3ExprCollSeqMatch(Parse*,Expr*,Expr*);
SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*, int);
SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*);
@@ -16574,7 +17934,9 @@ SQLITE_PRIVATE void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8,
SQLITE_PRIVATE void sqlite3ValueSetNull(sqlite3_value*);
SQLITE_PRIVATE void sqlite3ValueFree(sqlite3_value*);
SQLITE_PRIVATE sqlite3_value *sqlite3ValueNew(sqlite3 *);
+#ifndef SQLITE_OMIT_UTF16
SQLITE_PRIVATE char *sqlite3Utf16to8(sqlite3 *, const void*, int, u8);
+#endif
SQLITE_PRIVATE int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **);
SQLITE_PRIVATE void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8);
#ifndef SQLITE_AMALGAMATION
@@ -16670,8 +18032,10 @@ SQLITE_PRIVATE char sqlite3IndexColumnAffinity(sqlite3*, Index*, int);
/*
** The interface to the LEMON-generated parser
*/
-SQLITE_PRIVATE void *sqlite3ParserAlloc(void*(*)(u64));
-SQLITE_PRIVATE void sqlite3ParserFree(void*, void(*)(void*));
+#ifndef SQLITE_AMALGAMATION
+SQLITE_PRIVATE void *sqlite3ParserAlloc(void*(*)(u64));
+SQLITE_PRIVATE void sqlite3ParserFree(void*, void(*)(void*));
+#endif
SQLITE_PRIVATE void sqlite3Parser(void*, int, Token, Parse*);
#ifdef YYTRACKMAXSTACKDEPTH
SQLITE_PRIVATE int sqlite3ParserStackPeak(void*);
@@ -16717,6 +18081,13 @@ SQLITE_PRIVATE void sqlite3VtabUnlockList(sqlite3*);
SQLITE_PRIVATE int sqlite3VtabSavepoint(sqlite3 *, int, int);
SQLITE_PRIVATE void sqlite3VtabImportErrmsg(Vdbe*, sqlite3_vtab*);
SQLITE_PRIVATE VTable *sqlite3GetVTable(sqlite3*, Table*);
+SQLITE_PRIVATE Module *sqlite3VtabCreateModule(
+ sqlite3*,
+ const char*,
+ const sqlite3_module*,
+ void*,
+ void(*)(void*)
+ );
# define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0)
#endif
SQLITE_PRIVATE int sqlite3VtabEponymousTableInit(Parse*,Module*);
@@ -16774,6 +18145,7 @@ SQLITE_PRIVATE FKey *sqlite3FkReferences(Table *);
#define sqlite3FkDropTable(a,b,c)
#define sqlite3FkOldmask(a,b) 0
#define sqlite3FkRequired(a,b,c,d) 0
+ #define sqlite3FkReferences(a) 0
#endif
#ifndef SQLITE_OMIT_FOREIGN_KEY
SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *, Table*);
@@ -16792,10 +18164,10 @@ SQLITE_PRIVATE int sqlite3FkLocateIndex(Parse*,Table*,FKey*,Index**,int**);
/*
** The interface to the code in fault.c used for identifying "benign"
-** malloc failures. This is only present if SQLITE_OMIT_BUILTIN_TEST
+** malloc failures. This is only present if SQLITE_UNTESTABLE
** is not defined.
*/
-#ifndef SQLITE_OMIT_BUILTIN_TEST
+#ifndef SQLITE_UNTESTABLE
SQLITE_PRIVATE void sqlite3BeginBenignMalloc(void);
SQLITE_PRIVATE void sqlite3EndBenignMalloc(void);
#else
@@ -16821,7 +18193,8 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *, Expr *, u32, int*, int*);
SQLITE_PRIVATE int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int);
SQLITE_PRIVATE int sqlite3JournalSize(sqlite3_vfs *);
-#ifdef SQLITE_ENABLE_ATOMIC_WRITE
+#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \
+ || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
SQLITE_PRIVATE int sqlite3JournalCreate(sqlite3_file *);
#endif
@@ -16853,6 +18226,9 @@ SQLITE_PRIVATE void sqlite3ConnectionClosed(sqlite3 *db);
#ifdef SQLITE_DEBUG
SQLITE_PRIVATE void sqlite3ParserTrace(FILE*, char *);
#endif
+#if defined(YYCOVERAGE)
+SQLITE_PRIVATE int sqlite3ParserCoverage(FILE*);
+#endif
/*
** If the SQLITE_ENABLE IOTRACE exists then the global variable
@@ -16907,8 +18283,7 @@ SQLITE_PRIVATE int sqlite3MemdebugNoType(void*,u8);
#endif
#define MEMTYPE_HEAP 0x01 /* General heap allocations */
#define MEMTYPE_LOOKASIDE 0x02 /* Heap that might have been lookaside */
-#define MEMTYPE_SCRATCH 0x04 /* Scratch allocations */
-#define MEMTYPE_PCACHE 0x08 /* Page cache allocations */
+#define MEMTYPE_PCACHE 0x04 /* Page cache allocations */
/*
** Threading interface
@@ -16918,6 +18293,9 @@ SQLITE_PRIVATE int sqlite3ThreadCreate(SQLiteThread**,void*(*)(void*),void*);
SQLITE_PRIVATE int sqlite3ThreadJoin(SQLiteThread*, void**);
#endif
+#if defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST)
+SQLITE_PRIVATE int sqlite3DbpageRegister(sqlite3*);
+#endif
#if defined(SQLITE_ENABLE_DBSTAT_VTAB) || defined(SQLITE_TEST)
SQLITE_PRIVATE int sqlite3DbstatRegister(sqlite3*);
#endif
@@ -16926,6 +18304,11 @@ SQLITE_PRIVATE int sqlite3ExprVectorSize(Expr *pExpr);
SQLITE_PRIVATE int sqlite3ExprIsVector(Expr *pExpr);
SQLITE_PRIVATE Expr *sqlite3VectorFieldSubexpr(Expr*, int);
SQLITE_PRIVATE Expr *sqlite3ExprForVectorField(Parse*,Expr*,int);
+SQLITE_PRIVATE void sqlite3VectorErrorMsg(Parse*, Expr*);
+
+#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
+SQLITE_PRIVATE const char **sqlite3CompileOptions(int *pnOpt);
+#endif
#endif /* SQLITEINT_H */
@@ -17070,9 +18453,16 @@ SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[256] = {
** EVIDENCE-OF: R-43642-56306 By default, URI handling is globally
** disabled. The default value may be changed by compiling with the
** SQLITE_USE_URI symbol defined.
+**
+** URI filenames are enabled by default if SQLITE_HAS_CODEC is
+** enabled.
*/
#ifndef SQLITE_USE_URI
-# define SQLITE_USE_URI 0
+# ifdef SQLITE_HAS_CODEC
+# define SQLITE_USE_URI 1
+# else
+# define SQLITE_USE_URI 0
+# endif
#endif
/* EVIDENCE-OF: R-38720-18127 The default setting is determined by the
@@ -17102,6 +18492,19 @@ SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[256] = {
# define SQLITE_STMTJRNL_SPILL (64*1024)
#endif
+/*
+** The default lookaside-configuration, the format "SZ,N". SZ is the
+** number of bytes in each lookaside slot (should be a multiple of 8)
+** and N is the number of slots. The lookaside-configuration can be
+** changed as start-time using sqlite3_config(SQLITE_CONFIG_LOOKASIDE)
+** or at run-time for an individual database connection using
+** sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE);
+*/
+#ifndef SQLITE_DEFAULT_LOOKASIDE
+# define SQLITE_DEFAULT_LOOKASIDE 1200,100
+#endif
+
+
/*
** The following singleton contains the global configuration for
** the SQLite library.
@@ -17112,10 +18515,10 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
SQLITE_THREADSAFE==1, /* bFullMutex */
SQLITE_USE_URI, /* bOpenUri */
SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */
+ 0, /* bSmallMalloc */
0x7ffffffe, /* mxStrlen */
0, /* neverCorrupt */
- 128, /* szLookaside */
- 500, /* nLookaside */
+ SQLITE_DEFAULT_LOOKASIDE, /* szLookaside, nLookaside */
SQLITE_STMTJRNL_SPILL, /* nStmtSpill */
{0,0,0,0,0,0,0,0}, /* m */
{0,0,0,0,0,0,0,0,0}, /* mutex */
@@ -17125,9 +18528,6 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
0, 0, /* mnHeap, mxHeap */
SQLITE_DEFAULT_MMAP_SIZE, /* szMmap */
SQLITE_MAX_MMAP_SIZE, /* mxMmap */
- (void*)0, /* pScratch */
- 0, /* szScratch */
- 0, /* nScratch */
(void*)0, /* pPage */
0, /* szPage */
SQLITE_DEFAULT_PCACHE_INITSZ, /* nPage */
@@ -17152,7 +18552,7 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
0, /* xVdbeBranch */
0, /* pVbeBranchArg */
#endif
-#ifndef SQLITE_OMIT_BUILTIN_TEST
+#ifndef SQLITE_UNTESTABLE
0, /* xTestCallback */
#endif
0, /* bLocaltimeFault */
@@ -17212,460 +18612,6 @@ SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[] = OPFLG_INITIALIZER;
SQLITE_PRIVATE const char sqlite3StrBINARY[] = "BINARY";
/************** End of global.c **********************************************/
-/************** Begin file ctime.c *******************************************/
-/*
-** 2010 February 23
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-**
-** This file implements routines used to report what compile-time options
-** SQLite was built with.
-*/
-
-#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
-
-/* #include "sqliteInt.h" */
-
-/*
-** An array of names of all compile-time options. This array should
-** be sorted A-Z.
-**
-** This array looks large, but in a typical installation actually uses
-** only a handful of compile-time options, so most times this array is usually
-** rather short and uses little memory space.
-*/
-static const char * const azCompileOpt[] = {
-
-/* These macros are provided to "stringify" the value of the define
-** for those options in which the value is meaningful. */
-#define CTIMEOPT_VAL_(opt) #opt
-#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
-
-#if SQLITE_32BIT_ROWID
- "32BIT_ROWID",
-#endif
-#if SQLITE_4_BYTE_ALIGNED_MALLOC
- "4_BYTE_ALIGNED_MALLOC",
-#endif
-#if SQLITE_CASE_SENSITIVE_LIKE
- "CASE_SENSITIVE_LIKE",
-#endif
-#if SQLITE_CHECK_PAGES
- "CHECK_PAGES",
-#endif
-#if defined(__clang__) && defined(__clang_major__)
- "COMPILER=clang-" CTIMEOPT_VAL(__clang_major__) "."
- CTIMEOPT_VAL(__clang_minor__) "."
- CTIMEOPT_VAL(__clang_patchlevel__),
-#elif defined(_MSC_VER)
- "COMPILER=msvc-" CTIMEOPT_VAL(_MSC_VER),
-#elif defined(__GNUC__) && defined(__VERSION__)
- "COMPILER=gcc-" __VERSION__,
-#endif
-#if SQLITE_COVERAGE_TEST
- "COVERAGE_TEST",
-#endif
-#if SQLITE_DEBUG
- "DEBUG",
-#endif
-#if SQLITE_DEFAULT_LOCKING_MODE
- "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE),
-#endif
-#if defined(SQLITE_DEFAULT_MMAP_SIZE) && !defined(SQLITE_DEFAULT_MMAP_SIZE_xc)
- "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE),
-#endif
-#if SQLITE_DISABLE_DIRSYNC
- "DISABLE_DIRSYNC",
-#endif
-#if SQLITE_DISABLE_LFS
- "DISABLE_LFS",
-#endif
-#if SQLITE_ENABLE_8_3_NAMES
- "ENABLE_8_3_NAMES=" CTIMEOPT_VAL(SQLITE_ENABLE_8_3_NAMES),
-#endif
-#if SQLITE_ENABLE_API_ARMOR
- "ENABLE_API_ARMOR",
-#endif
-#if SQLITE_ENABLE_ATOMIC_WRITE
- "ENABLE_ATOMIC_WRITE",
-#endif
-#if SQLITE_ENABLE_CEROD
- "ENABLE_CEROD",
-#endif
-#if SQLITE_ENABLE_COLUMN_METADATA
- "ENABLE_COLUMN_METADATA",
-#endif
-#if SQLITE_ENABLE_DBSTAT_VTAB
- "ENABLE_DBSTAT_VTAB",
-#endif
-#if SQLITE_ENABLE_EXPENSIVE_ASSERT
- "ENABLE_EXPENSIVE_ASSERT",
-#endif
-#if SQLITE_ENABLE_FTS1
- "ENABLE_FTS1",
-#endif
-#if SQLITE_ENABLE_FTS2
- "ENABLE_FTS2",
-#endif
-#if SQLITE_ENABLE_FTS3
- "ENABLE_FTS3",
-#endif
-#if SQLITE_ENABLE_FTS3_PARENTHESIS
- "ENABLE_FTS3_PARENTHESIS",
-#endif
-#if SQLITE_ENABLE_FTS4
- "ENABLE_FTS4",
-#endif
-#if SQLITE_ENABLE_FTS5
- "ENABLE_FTS5",
-#endif
-#if SQLITE_ENABLE_ICU
- "ENABLE_ICU",
-#endif
-#if SQLITE_ENABLE_IOTRACE
- "ENABLE_IOTRACE",
-#endif
-#if SQLITE_ENABLE_JSON1
- "ENABLE_JSON1",
-#endif
-#if SQLITE_ENABLE_LOAD_EXTENSION
- "ENABLE_LOAD_EXTENSION",
-#endif
-#if SQLITE_ENABLE_LOCKING_STYLE
- "ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE),
-#endif
-#if SQLITE_ENABLE_MEMORY_MANAGEMENT
- "ENABLE_MEMORY_MANAGEMENT",
-#endif
-#if SQLITE_ENABLE_MEMSYS3
- "ENABLE_MEMSYS3",
-#endif
-#if SQLITE_ENABLE_MEMSYS5
- "ENABLE_MEMSYS5",
-#endif
-#if SQLITE_ENABLE_OVERSIZE_CELL_CHECK
- "ENABLE_OVERSIZE_CELL_CHECK",
-#endif
-#if SQLITE_ENABLE_RTREE
- "ENABLE_RTREE",
-#endif
-#if defined(SQLITE_ENABLE_STAT4)
- "ENABLE_STAT4",
-#elif defined(SQLITE_ENABLE_STAT3)
- "ENABLE_STAT3",
-#endif
-#if SQLITE_ENABLE_UNLOCK_NOTIFY
- "ENABLE_UNLOCK_NOTIFY",
-#endif
-#if SQLITE_ENABLE_UPDATE_DELETE_LIMIT
- "ENABLE_UPDATE_DELETE_LIMIT",
-#endif
-#if SQLITE_HAS_CODEC
- "HAS_CODEC",
-#endif
-#if HAVE_ISNAN || SQLITE_HAVE_ISNAN
- "HAVE_ISNAN",
-#endif
-#if SQLITE_HOMEGROWN_RECURSIVE_MUTEX
- "HOMEGROWN_RECURSIVE_MUTEX",
-#endif
-#if SQLITE_IGNORE_AFP_LOCK_ERRORS
- "IGNORE_AFP_LOCK_ERRORS",
-#endif
-#if SQLITE_IGNORE_FLOCK_LOCK_ERRORS
- "IGNORE_FLOCK_LOCK_ERRORS",
-#endif
-#ifdef SQLITE_INT64_TYPE
- "INT64_TYPE",
-#endif
-#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS
- "LIKE_DOESNT_MATCH_BLOBS",
-#endif
-#if SQLITE_LOCK_TRACE
- "LOCK_TRACE",
-#endif
-#if defined(SQLITE_MAX_MMAP_SIZE) && !defined(SQLITE_MAX_MMAP_SIZE_xc)
- "MAX_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE),
-#endif
-#ifdef SQLITE_MAX_SCHEMA_RETRY
- "MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY),
-#endif
-#if SQLITE_MEMDEBUG
- "MEMDEBUG",
-#endif
-#if SQLITE_MIXED_ENDIAN_64BIT_FLOAT
- "MIXED_ENDIAN_64BIT_FLOAT",
-#endif
-#if SQLITE_NO_SYNC
- "NO_SYNC",
-#endif
-#if SQLITE_OMIT_ALTERTABLE
- "OMIT_ALTERTABLE",
-#endif
-#if SQLITE_OMIT_ANALYZE
- "OMIT_ANALYZE",
-#endif
-#if SQLITE_OMIT_ATTACH
- "OMIT_ATTACH",
-#endif
-#if SQLITE_OMIT_AUTHORIZATION
- "OMIT_AUTHORIZATION",
-#endif
-#if SQLITE_OMIT_AUTOINCREMENT
- "OMIT_AUTOINCREMENT",
-#endif
-#if SQLITE_OMIT_AUTOINIT
- "OMIT_AUTOINIT",
-#endif
-#if SQLITE_OMIT_AUTOMATIC_INDEX
- "OMIT_AUTOMATIC_INDEX",
-#endif
-#if SQLITE_OMIT_AUTORESET
- "OMIT_AUTORESET",
-#endif
-#if SQLITE_OMIT_AUTOVACUUM
- "OMIT_AUTOVACUUM",
-#endif
-#if SQLITE_OMIT_BETWEEN_OPTIMIZATION
- "OMIT_BETWEEN_OPTIMIZATION",
-#endif
-#if SQLITE_OMIT_BLOB_LITERAL
- "OMIT_BLOB_LITERAL",
-#endif
-#if SQLITE_OMIT_BTREECOUNT
- "OMIT_BTREECOUNT",
-#endif
-#if SQLITE_OMIT_BUILTIN_TEST
- "OMIT_BUILTIN_TEST",
-#endif
-#if SQLITE_OMIT_CAST
- "OMIT_CAST",
-#endif
-#if SQLITE_OMIT_CHECK
- "OMIT_CHECK",
-#endif
-#if SQLITE_OMIT_COMPLETE
- "OMIT_COMPLETE",
-#endif
-#if SQLITE_OMIT_COMPOUND_SELECT
- "OMIT_COMPOUND_SELECT",
-#endif
-#if SQLITE_OMIT_CTE
- "OMIT_CTE",
-#endif
-#if SQLITE_OMIT_DATETIME_FUNCS
- "OMIT_DATETIME_FUNCS",
-#endif
-#if SQLITE_OMIT_DECLTYPE
- "OMIT_DECLTYPE",
-#endif
-#if SQLITE_OMIT_DEPRECATED
- "OMIT_DEPRECATED",
-#endif
-#if SQLITE_OMIT_DISKIO
- "OMIT_DISKIO",
-#endif
-#if SQLITE_OMIT_EXPLAIN
- "OMIT_EXPLAIN",
-#endif
-#if SQLITE_OMIT_FLAG_PRAGMAS
- "OMIT_FLAG_PRAGMAS",
-#endif
-#if SQLITE_OMIT_FLOATING_POINT
- "OMIT_FLOATING_POINT",
-#endif
-#if SQLITE_OMIT_FOREIGN_KEY
- "OMIT_FOREIGN_KEY",
-#endif
-#if SQLITE_OMIT_GET_TABLE
- "OMIT_GET_TABLE",
-#endif
-#if SQLITE_OMIT_INCRBLOB
- "OMIT_INCRBLOB",
-#endif
-#if SQLITE_OMIT_INTEGRITY_CHECK
- "OMIT_INTEGRITY_CHECK",
-#endif
-#if SQLITE_OMIT_LIKE_OPTIMIZATION
- "OMIT_LIKE_OPTIMIZATION",
-#endif
-#if SQLITE_OMIT_LOAD_EXTENSION
- "OMIT_LOAD_EXTENSION",
-#endif
-#if SQLITE_OMIT_LOCALTIME
- "OMIT_LOCALTIME",
-#endif
-#if SQLITE_OMIT_LOOKASIDE
- "OMIT_LOOKASIDE",
-#endif
-#if SQLITE_OMIT_MEMORYDB
- "OMIT_MEMORYDB",
-#endif
-#if SQLITE_OMIT_OR_OPTIMIZATION
- "OMIT_OR_OPTIMIZATION",
-#endif
-#if SQLITE_OMIT_PAGER_PRAGMAS
- "OMIT_PAGER_PRAGMAS",
-#endif
-#if SQLITE_OMIT_PRAGMA
- "OMIT_PRAGMA",
-#endif
-#if SQLITE_OMIT_PROGRESS_CALLBACK
- "OMIT_PROGRESS_CALLBACK",
-#endif
-#if SQLITE_OMIT_QUICKBALANCE
- "OMIT_QUICKBALANCE",
-#endif
-#if SQLITE_OMIT_REINDEX
- "OMIT_REINDEX",
-#endif
-#if SQLITE_OMIT_SCHEMA_PRAGMAS
- "OMIT_SCHEMA_PRAGMAS",
-#endif
-#if SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
- "OMIT_SCHEMA_VERSION_PRAGMAS",
-#endif
-#if SQLITE_OMIT_SHARED_CACHE
- "OMIT_SHARED_CACHE",
-#endif
-#if SQLITE_OMIT_SUBQUERY
- "OMIT_SUBQUERY",
-#endif
-#if SQLITE_OMIT_TCL_VARIABLE
- "OMIT_TCL_VARIABLE",
-#endif
-#if SQLITE_OMIT_TEMPDB
- "OMIT_TEMPDB",
-#endif
-#if SQLITE_OMIT_TRACE
- "OMIT_TRACE",
-#endif
-#if SQLITE_OMIT_TRIGGER
- "OMIT_TRIGGER",
-#endif
-#if SQLITE_OMIT_TRUNCATE_OPTIMIZATION
- "OMIT_TRUNCATE_OPTIMIZATION",
-#endif
-#if SQLITE_OMIT_UTF16
- "OMIT_UTF16",
-#endif
-#if SQLITE_OMIT_VACUUM
- "OMIT_VACUUM",
-#endif
-#if SQLITE_OMIT_VIEW
- "OMIT_VIEW",
-#endif
-#if SQLITE_OMIT_VIRTUALTABLE
- "OMIT_VIRTUALTABLE",
-#endif
-#if SQLITE_OMIT_WAL
- "OMIT_WAL",
-#endif
-#if SQLITE_OMIT_WSD
- "OMIT_WSD",
-#endif
-#if SQLITE_OMIT_XFER_OPT
- "OMIT_XFER_OPT",
-#endif
-#if SQLITE_PERFORMANCE_TRACE
- "PERFORMANCE_TRACE",
-#endif
-#if SQLITE_PROXY_DEBUG
- "PROXY_DEBUG",
-#endif
-#if SQLITE_RTREE_INT_ONLY
- "RTREE_INT_ONLY",
-#endif
-#if SQLITE_SECURE_DELETE
- "SECURE_DELETE",
-#endif
-#if SQLITE_SMALL_STACK
- "SMALL_STACK",
-#endif
-#if SQLITE_SOUNDEX
- "SOUNDEX",
-#endif
-#if SQLITE_SYSTEM_MALLOC
- "SYSTEM_MALLOC",
-#endif
-#if SQLITE_TCL
- "TCL",
-#endif
-#if defined(SQLITE_TEMP_STORE) && !defined(SQLITE_TEMP_STORE_xc)
- "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE),
-#endif
-#if SQLITE_TEST
- "TEST",
-#endif
-#if defined(SQLITE_THREADSAFE)
- "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE),
-#endif
-#if SQLITE_USE_ALLOCA
- "USE_ALLOCA",
-#endif
-#if SQLITE_USER_AUTHENTICATION
- "USER_AUTHENTICATION",
-#endif
-#if SQLITE_WIN32_MALLOC
- "WIN32_MALLOC",
-#endif
-#if SQLITE_ZERO_MALLOC
- "ZERO_MALLOC"
-#endif
-};
-
-/*
-** Given the name of a compile-time option, return true if that option
-** was used and false if not.
-**
-** The name can optionally begin with "SQLITE_" but the "SQLITE_" prefix
-** is not required for a match.
-*/
-SQLITE_API int sqlite3_compileoption_used(const char *zOptName){
- int i, n;
-
-#if SQLITE_ENABLE_API_ARMOR
- if( zOptName==0 ){
- (void)SQLITE_MISUSE_BKPT;
- return 0;
- }
-#endif
- if( sqlite3StrNICmp(zOptName, "SQLITE_", 7)==0 ) zOptName += 7;
- n = sqlite3Strlen30(zOptName);
-
- /* Since ArraySize(azCompileOpt) is normally in single digits, a
- ** linear search is adequate. No need for a binary search. */
- for(i=0; i=0 && NaDb[] (or -1) */
- u8 nullRow; /* True if pointing to a row with no data */
- u8 deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */
- u8 isTable; /* True for rowid tables. False for indexes */
+ u8 eCurType; /* One of the CURTYPE_* values above */
+ i8 iDb; /* Index of cursor database in db->aDb[] (or -1) */
+ u8 nullRow; /* True if pointing to a row with no data */
+ u8 deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */
+ u8 isTable; /* True for rowid tables. False for indexes */
#ifdef SQLITE_DEBUG
- u8 seekOp; /* Most recent seek operation on this cursor */
- u8 wrFlag; /* The wrFlag argument to sqlite3BtreeCursor() */
-#endif
- Bool isEphemeral:1; /* True for an ephemeral table */
- Bool useRandomRowid:1;/* Generate new record numbers semi-randomly */
- Bool isOrdered:1; /* True if the table is not BTREE_UNORDERED */
- Pgno pgnoRoot; /* Root page of the open btree cursor */
- i16 nField; /* Number of fields in the header */
- u16 nHdrParsed; /* Number of header fields parsed so far */
+ u8 seekOp; /* Most recent seek operation on this cursor */
+ u8 wrFlag; /* The wrFlag argument to sqlite3BtreeCursor() */
+#endif
+ Bool isEphemeral:1; /* True for an ephemeral table */
+ Bool useRandomRowid:1; /* Generate new record numbers semi-randomly */
+ Bool isOrdered:1; /* True if the table is not BTREE_UNORDERED */
+ Btree *pBtx; /* Separate file holding temporary table */
+ i64 seqCount; /* Sequence counter */
+ int *aAltMap; /* Mapping from table to index column numbers */
+
+ /* Cached OP_Column parse information is only valid if cacheStatus matches
+ ** Vdbe.cacheCtr. Vdbe.cacheCtr will never take on the value of
+ ** CACHE_STALE (0) and so setting cacheStatus=CACHE_STALE guarantees that
+ ** the cache is out of date. */
+ u32 cacheStatus; /* Cache is valid if this matches Vdbe.cacheCtr */
+ int seekResult; /* Result of previous sqlite3BtreeMoveto() or 0
+ ** if there have been no prior seeks on the cursor. */
+ /* seekResult does not distinguish between "no seeks have ever occurred
+ ** on this cursor" and "the most recent seek was an exact match".
+ ** For CURTYPE_PSEUDO, seekResult is the register holding the record */
+
+ /* When a new VdbeCursor is allocated, only the fields above are zeroed.
+ ** The fields that follow are uninitialized, and must be individually
+ ** initialized prior to first use. */
+ VdbeCursor *pAltCursor; /* Associated index cursor from which to read */
union {
- BtCursor *pCursor; /* CURTYPE_BTREE. Btree cursor */
- sqlite3_vtab_cursor *pVCur; /* CURTYPE_VTAB. Vtab cursor */
- int pseudoTableReg; /* CURTYPE_PSEUDO. Reg holding content. */
- VdbeSorter *pSorter; /* CURTYPE_SORTER. Sorter object */
+ BtCursor *pCursor; /* CURTYPE_BTREE or _PSEUDO. Btree cursor */
+ sqlite3_vtab_cursor *pVCur; /* CURTYPE_VTAB. Vtab cursor */
+ VdbeSorter *pSorter; /* CURTYPE_SORTER. Sorter object */
} uc;
- Btree *pBt; /* Separate file holding temporary table */
- KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */
- int seekResult; /* Result of previous sqlite3BtreeMoveto() */
- i64 seqCount; /* Sequence counter */
- i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
- VdbeCursor *pAltCursor; /* Associated index cursor from which to read */
- int *aAltMap; /* Mapping from table to index column numbers */
+ KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */
+ u32 iHdrOffset; /* Offset to next unparsed byte of the header */
+ Pgno pgnoRoot; /* Root page of the open btree cursor */
+ i16 nField; /* Number of fields in the header */
+ u16 nHdrParsed; /* Number of header fields parsed so far */
+ i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
+ u32 *aOffset; /* Pointer to aType[nField] */
+ const u8 *aRow; /* Data for the current row, if all on one page */
+ u32 payloadSize; /* Total number of bytes in the record */
+ u32 szRow; /* Byte available in aRow */
#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
- u64 maskUsed; /* Mask of columns used by this cursor */
+ u64 maskUsed; /* Mask of columns used by this cursor */
#endif
- /* Cached information about the header for the data record that the
- ** cursor is currently pointing to. Only valid if cacheStatus matches
- ** Vdbe.cacheCtr. Vdbe.cacheCtr will never take on the value of
- ** CACHE_STALE and so setting cacheStatus=CACHE_STALE guarantees that
- ** the cache is out of date.
- **
- ** aRow might point to (ephemeral) data for the current row, or it might
- ** be NULL.
- */
- u32 cacheStatus; /* Cache is valid if this matches Vdbe.cacheCtr */
- u32 payloadSize; /* Total number of bytes in the record */
- u32 szRow; /* Byte available in aRow */
- u32 iHdrOffset; /* Offset to next unparsed byte of the header */
- const u8 *aRow; /* Data for the current row, if all on one page */
- u32 *aOffset; /* Pointer to aType[nField] */
- u32 aType[1]; /* Type values for all entries in the record */
/* 2*nField extra array elements allocated for aType[], beyond the one
** static element declared in the structure. nField total array slots for
** aType[] and nField+1 array slots for aOffset[] */
+ u32 aType[1]; /* Type values record decode. MUST BE LAST */
};
@@ -17848,6 +18797,7 @@ struct VdbeFrame {
i64 *anExec; /* Event counters from parent frame */
Mem *aMem; /* Array of memory cells for parent frame */
VdbeCursor **apCsr; /* Array of Vdbe cursors for parent frame */
+ u8 *aOnce; /* Bitmask used by OP_Once */
void *token; /* Copy of SubProgram.token */
i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */
AuxData *pAuxData; /* Linked list of auxdata allocations */
@@ -17868,11 +18818,12 @@ struct VdbeFrame {
** structures. Each Mem struct may cache multiple representations (string,
** integer etc.) of the same value.
*/
-struct Mem {
+struct sqlite3_value {
union MemValue {
double r; /* Real value used when MEM_Real is set in flags */
i64 i; /* Integer value used when MEM_Int is set in flags */
- int nZero; /* Used when bit MEM_Zero is set in flags */
+ int nZero; /* Extra zero bytes when MEM_Zero and MEM_Blob set */
+ const char *zPType; /* Pointer type when MEM_Term|MEM_Subtype|MEM_Null */
FuncDef *pDef; /* Used only when flags==MEM_Agg */
RowSet *pRowSet; /* Used only when flags==MEM_RowSet */
VdbeFrame *pFrame; /* Used when flags==MEM_Frame */
@@ -17904,7 +18855,10 @@ struct Mem {
** representations of the value stored in the Mem struct.
**
** If the MEM_Null flag is set, then the value is an SQL NULL value.
-** No other flags may be set in this case.
+** For a pointer type created using sqlite3_bind_pointer() or
+** sqlite3_result_pointer() the MEM_Term and MEM_Subtype flags are also set.
+** If both MEM_Null and MEM_Zero are set, that means that the value is
+** an unchanging column value from VColumn.
**
** If the MEM_Str flag is set then Mem.z points at a string representation.
** Usually this is encoded in the same unicode encoding as the main
@@ -17912,7 +18866,7 @@ struct Mem {
** set, then the string is nul terminated. The MEM_Int and MEM_Real
** flags may coexist with the MEM_Str flag.
*/
-#define MEM_Null 0x0001 /* Value is NULL */
+#define MEM_Null 0x0001 /* Value is NULL (or a pointer) */
#define MEM_Str 0x0002 /* Value is a string */
#define MEM_Int 0x0004 /* Value is an integer */
#define MEM_Real 0x0008 /* Value is a real number */
@@ -17922,7 +18876,7 @@ struct Mem {
#define MEM_Frame 0x0040 /* Value is a VdbeFrame object */
#define MEM_Undefined 0x0080 /* Value is undefined */
#define MEM_Cleared 0x0100 /* NULL set by OP_Null, not from data */
-#define MEM_TypeMask 0x81ff /* Mask of type bits */
+#define MEM_TypeMask 0xc1ff /* Mask of type bits */
/* Whenever Mem contains a valid string or blob representation, one of
@@ -17930,7 +18884,7 @@ struct Mem {
** policy for Mem.z. The MEM_Term flag tells us whether or not the
** string is \000 or \u0000 terminated
*/
-#define MEM_Term 0x0200 /* String rep is nul terminated */
+#define MEM_Term 0x0200 /* String in Mem.z is zero terminated */
#define MEM_Dyn 0x0400 /* Need to call Mem.xDel() on Mem.z */
#define MEM_Static 0x0800 /* Mem.z points to a static string */
#define MEM_Ephem 0x1000 /* Mem.z points to an ephemeral string */
@@ -17970,11 +18924,11 @@ struct Mem {
** when the VM is halted (if not before).
*/
struct AuxData {
- int iOp; /* Instruction number of OP_Function opcode */
- int iArg; /* Index of function argument. */
+ int iAuxOp; /* Instruction number of OP_Function opcode */
+ int iAuxArg; /* Index of function argument. */
void *pAux; /* Aux data pointer */
- void (*xDelete)(void *); /* Destructor for the aux data */
- AuxData *pNext; /* Next element in list */
+ void (*xDeleteAux)(void*); /* Destructor for the aux data */
+ AuxData *pNextAux; /* Next element in list */
};
/*
@@ -18030,7 +18984,6 @@ struct Vdbe {
Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */
Parse *pParse; /* Parsing context used to create this Vdbe */
ynVar nVar; /* Number of entries in aVar[] */
- ynVar nzVar; /* Number of entries in azVar[] */
u32 magic; /* Magic number for sanity checking */
int nMem; /* Number of memory locations currently allocated */
int nCursor; /* Number of slots in apCsr[] */
@@ -18055,7 +19008,7 @@ struct Vdbe {
char *zErrMsg; /* Error message written here */
VdbeCursor **apCsr; /* One element of this array for each open cursor */
Mem *aVar; /* Values for the OP_Variable opcode. */
- char **azVar; /* Name of variables */
+ VList *pVList; /* Name of variables */
#ifndef SQLITE_OMIT_TRACE
i64 startTime; /* Time when query started - used for profiling */
#endif
@@ -18066,6 +19019,7 @@ struct Vdbe {
u16 nResColumn; /* Number of columns in one row of the result set */
u8 errorAction; /* Recovery action to do in case of an error */
u8 minWriteFileFormat; /* Minimum file format for writable database files */
+ u8 prepFlags; /* SQLITE_PREPARE_* flags */
bft expired:1; /* True if the VM needs to be recompiled */
bft doingRerun:1; /* True if rerunning after an auto-reprepare */
bft explain:2; /* True if EXPLAIN present on SQL command */
@@ -18074,10 +19028,9 @@ struct Vdbe {
bft usesStmtJournal:1; /* True if uses a statement journal */
bft readOnly:1; /* True for statements that do not write */
bft bIsReader:1; /* True for statements that read */
- bft isPrepareV2:1; /* True if prepared with prepare_v2() */
yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */
yDbMask lockMask; /* Subset of btreeMask that requires a lock */
- u32 aCounter[5]; /* Counters used by sqlite3_stmt_status() */
+ u32 aCounter[7]; /* Counters used by sqlite3_stmt_status() */
char *zSql; /* Text of the SQL statement that generated this */
void *pFree; /* Free this when deleting the vdbe */
VdbeFrame *pFrame; /* Parent frame */
@@ -18119,6 +19072,7 @@ struct PreUpdate {
i64 iKey2; /* Second key value passed to hook */
Mem *aNew; /* Array of new.* values */
Table *pTab; /* Schema object being upated */
+ Index *pPk; /* PK index if pTab is WITHOUT ROWID */
};
/*
@@ -18158,6 +19112,7 @@ SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem*, i64);
#else
SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem*, double);
#endif
+SQLITE_PRIVATE void sqlite3VdbeMemSetPointer(Mem*, void*, const char*, void(*)(void*));
SQLITE_PRIVATE void sqlite3VdbeMemInit(Mem*,sqlite3*,u16);
SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem*);
SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem*,int);
@@ -18171,7 +19126,7 @@ SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*);
SQLITE_PRIVATE void sqlite3VdbeMemCast(Mem*,u8,u8);
-SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,int,Mem*);
+SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,Mem*);
SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p);
SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
SQLITE_PRIVATE const char *sqlite3OpcodeName(int);
@@ -18189,7 +19144,7 @@ SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, int, VdbeCursor *);
SQLITE_PRIVATE void sqlite3VdbeSorterReset(sqlite3 *, VdbeSorter *);
SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *);
SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(const VdbeCursor *, Mem *);
-SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *, int *);
+SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *);
SQLITE_PRIVATE int sqlite3VdbeSorterRewind(const VdbeCursor *, int *);
SQLITE_PRIVATE int sqlite3VdbeSorterWrite(const VdbeCursor *, Mem *);
SQLITE_PRIVATE int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int, int *);
@@ -18217,12 +19172,14 @@ SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *, int);
# define sqlite3VdbeCheckFk(p,i) 0
#endif
-SQLITE_PRIVATE int sqlite3VdbeMemTranslate(Mem*, u8);
#ifdef SQLITE_DEBUG
SQLITE_PRIVATE void sqlite3VdbePrintSql(Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf);
#endif
-SQLITE_PRIVATE int sqlite3VdbeMemHandleBom(Mem *pMem);
+#ifndef SQLITE_OMIT_UTF16
+SQLITE_PRIVATE int sqlite3VdbeMemTranslate(Mem*, u8);
+SQLITE_PRIVATE int sqlite3VdbeMemHandleBom(Mem *pMem);
+#endif
#ifndef SQLITE_OMIT_INCRBLOB
SQLITE_PRIVATE int sqlite3VdbeMemExpandBlob(Mem *);
@@ -18343,7 +19300,6 @@ SQLITE_PRIVATE void sqlite3StatusHighwater(int op, int X){
: sqlite3MallocMutex()) );
assert( op==SQLITE_STATUS_MALLOC_SIZE
|| op==SQLITE_STATUS_PAGECACHE_SIZE
- || op==SQLITE_STATUS_SCRATCH_SIZE
|| op==SQLITE_STATUS_PARSER_STACK );
if( newValue>wsdStat.mxValue[op] ){
wsdStat.mxValue[op] = newValue;
@@ -18392,6 +19348,28 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF
return rc;
}
+/*
+** Return the number of LookasideSlot elements on the linked list
+*/
+static u32 countLookasideSlots(LookasideSlot *p){
+ u32 cnt = 0;
+ while( p ){
+ p = p->pNext;
+ cnt++;
+ }
+ return cnt;
+}
+
+/*
+** Count the number of slots of lookaside memory that are outstanding
+*/
+SQLITE_PRIVATE int sqlite3LookasideUsed(sqlite3 *db, int *pHighwater){
+ u32 nInit = countLookasideSlots(db->lookaside.pInit);
+ u32 nFree = countLookasideSlots(db->lookaside.pFree);
+ if( pHighwater ) *pHighwater = db->lookaside.nSlot - nInit;
+ return db->lookaside.nSlot - (nInit+nFree);
+}
+
/*
** Query status information for a single database connection
*/
@@ -18411,10 +19389,15 @@ SQLITE_API int sqlite3_db_status(
sqlite3_mutex_enter(db->mutex);
switch( op ){
case SQLITE_DBSTATUS_LOOKASIDE_USED: {
- *pCurrent = db->lookaside.nOut;
- *pHighwater = db->lookaside.mxOut;
+ *pCurrent = sqlite3LookasideUsed(db, pHighwater);
if( resetFlag ){
- db->lookaside.mxOut = db->lookaside.nOut;
+ LookasideSlot *p = db->lookaside.pFree;
+ if( p ){
+ while( p->pNext ) p = p->pNext;
+ p->pNext = db->lookaside.pInit;
+ db->lookaside.pInit = db->lookaside.pFree;
+ db->lookaside.pFree = 0;
+ }
}
break;
}
@@ -18614,7 +19597,7 @@ SQLITE_API int sqlite3_db_status(
**
** Jean Meeus
** Astronomical Algorithms, 2nd Edition, 1998
-** ISBM 0-943396-61-1
+** ISBN 0-943396-61-1
** Willmann-Bell, Inc
** Richmond, Virginia (USA)
*/
@@ -18640,16 +19623,18 @@ struct tm *__cdecl localtime(const time_t *);
*/
typedef struct DateTime DateTime;
struct DateTime {
- sqlite3_int64 iJD; /* The julian day number times 86400000 */
- int Y, M, D; /* Year, month, and day */
- int h, m; /* Hour and minutes */
- int tz; /* Timezone offset in minutes */
- double s; /* Seconds */
- char validYMD; /* True (1) if Y,M,D are valid */
- char validHMS; /* True (1) if h,m,s are valid */
- char validJD; /* True (1) if iJD is valid */
- char validTZ; /* True (1) if tz is valid */
- char tzSet; /* Timezone was set explicitly */
+ sqlite3_int64 iJD; /* The julian day number times 86400000 */
+ int Y, M, D; /* Year, month, and day */
+ int h, m; /* Hour and minutes */
+ int tz; /* Timezone offset in minutes */
+ double s; /* Seconds */
+ char validJD; /* True (1) if iJD is valid */
+ char rawS; /* Raw numeric value stored in s */
+ char validYMD; /* True (1) if Y,M,D are valid */
+ char validHMS; /* True (1) if h,m,s are valid */
+ char validTZ; /* True (1) if tz is valid */
+ char tzSet; /* Timezone was set explicitly */
+ char isError; /* An overflow has occurred */
};
@@ -18797,6 +19782,7 @@ static int parseHhMmSs(const char *zDate, DateTime *p){
s = 0;
}
p->validJD = 0;
+ p->rawS = 0;
p->validHMS = 1;
p->h = h;
p->m = m;
@@ -18806,6 +19792,14 @@ static int parseHhMmSs(const char *zDate, DateTime *p){
return 0;
}
+/*
+** Put the DateTime object into its error state.
+*/
+static void datetimeError(DateTime *p){
+ memset(p, 0, sizeof(*p));
+ p->isError = 1;
+}
+
/*
** Convert from YYYY-MM-DD HH:MM:SS to julian day. We always assume
** that the YYYY-MM-DD is according to the Gregorian calendar.
@@ -18825,6 +19819,10 @@ static void computeJD(DateTime *p){
M = 1;
D = 1;
}
+ if( Y<-4713 || Y>9999 || p->rawS ){
+ datetimeError(p);
+ return;
+ }
if( M<=2 ){
Y--;
M += 12;
@@ -18905,6 +19903,21 @@ static int setDateTimeToCurrent(sqlite3_context *context, DateTime *p){
}
}
+/*
+** Input "r" is a numeric quantity which might be a julian day number,
+** or the number of seconds since 1970. If the value if r is within
+** range of a julian day number, install it as such and set validJD.
+** If the value is a valid unix timestamp, put it in p->s and set p->rawS.
+*/
+static void setRawDateNumber(DateTime *p, double r){
+ p->s = r;
+ p->rawS = 1;
+ if( r>=0.0 && r<5373484.5 ){
+ p->iJD = (sqlite3_int64)(r*86400000.0 + 0.5);
+ p->validJD = 1;
+ }
+}
+
/*
** Attempt to parse the given string into a julian day number. Return
** the number of errors.
@@ -18931,16 +19944,33 @@ static int parseDateOrTime(
return 0;
}else if( parseHhMmSs(zDate, p)==0 ){
return 0;
- }else if( sqlite3StrICmp(zDate,"now")==0){
+ }else if( sqlite3StrICmp(zDate,"now")==0 && sqlite3NotPureFunc(context) ){
return setDateTimeToCurrent(context, p);
}else if( sqlite3AtoF(zDate, &r, sqlite3Strlen30(zDate), SQLITE_UTF8) ){
- p->iJD = (sqlite3_int64)(r*86400000.0 + 0.5);
- p->validJD = 1;
+ setRawDateNumber(p, r);
return 0;
}
return 1;
}
+/* The julian day number for 9999-12-31 23:59:59.999 is 5373484.4999999.
+** Multiplying this by 86400000 gives 464269060799999 as the maximum value
+** for DateTime.iJD.
+**
+** But some older compilers (ex: gcc 4.2.1 on older Macs) cannot deal with
+** such a large integer literal, so we have to encode it.
+*/
+#define INT_464269060799999 ((((i64)0x1a640)<<32)|0x1072fdff)
+
+/*
+** Return TRUE if the given julian day number is within range.
+**
+** The input is the JulianDay times 86400000.
+*/
+static int validJulianDay(sqlite3_int64 iJD){
+ return iJD>=0 && iJD<=INT_464269060799999;
+}
+
/*
** Compute the Year, Month, and Day from the julian day number.
*/
@@ -18951,6 +19981,9 @@ static void computeYMD(DateTime *p){
p->Y = 2000;
p->M = 1;
p->D = 1;
+ }else if( !validJulianDay(p->iJD) ){
+ datetimeError(p);
+ return;
}else{
Z = (int)((p->iJD + 43200000)/86400000);
A = (int)((Z - 1867216.25)/36524.25);
@@ -18982,6 +20015,7 @@ static void computeHMS(DateTime *p){
s -= p->h*3600;
p->m = s/60;
p->s += s - p->m*60;
+ p->rawS = 0;
p->validHMS = 1;
}
@@ -19043,14 +20077,14 @@ static int osLocaltime(time_t *t, struct tm *pTm){
#endif
sqlite3_mutex_enter(mutex);
pX = localtime(t);
-#ifndef SQLITE_OMIT_BUILTIN_TEST
+#ifndef SQLITE_UNTESTABLE
if( sqlite3GlobalConfig.bLocaltimeFault ) pX = 0;
#endif
if( pX ) *pTm = *pX;
sqlite3_mutex_leave(mutex);
rc = pX==0;
#else
-#ifndef SQLITE_OMIT_BUILTIN_TEST
+#ifndef SQLITE_UNTESTABLE
if( sqlite3GlobalConfig.bLocaltimeFault ) return 1;
#endif
#if HAVE_LOCALTIME_R
@@ -19121,13 +20155,38 @@ static sqlite3_int64 localtimeOffset(
y.validYMD = 1;
y.validHMS = 1;
y.validJD = 0;
+ y.rawS = 0;
y.validTZ = 0;
+ y.isError = 0;
computeJD(&y);
*pRc = SQLITE_OK;
return y.iJD - x.iJD;
}
#endif /* SQLITE_OMIT_LOCALTIME */
+/*
+** The following table defines various date transformations of the form
+**
+** 'NNN days'
+**
+** Where NNN is an arbitrary floating-point number and "days" can be one
+** of several units of time.
+*/
+static const struct {
+ u8 eType; /* Transformation type code */
+ u8 nName; /* Length of th name */
+ char *zName; /* Name of the transformation */
+ double rLimit; /* Maximum NNN value for this transform */
+ double rXform; /* Constant used for this transform */
+} aXformType[] = {
+ { 0, 6, "second", 464269060800.0, 86400000.0/(24.0*60.0*60.0) },
+ { 0, 6, "minute", 7737817680.0, 86400000.0/(24.0*60.0) },
+ { 0, 4, "hour", 128963628.0, 86400000.0/24.0 },
+ { 0, 3, "day", 5373485.0, 86400000.0 },
+ { 1, 5, "month", 176546.0, 30.0*86400000.0 },
+ { 2, 4, "year", 14713.0, 365.0*86400000.0 },
+};
+
/*
** Process a modifier to a date-time stamp. The modifiers are
** as follows:
@@ -19152,17 +20211,15 @@ static sqlite3_int64 localtimeOffset(
** to context pCtx. If the error is an unrecognized modifier, no error is
** written to pCtx.
*/
-static int parseModifier(sqlite3_context *pCtx, const char *zMod, DateTime *p){
+static int parseModifier(
+ sqlite3_context *pCtx, /* Function context */
+ const char *z, /* The text of the modifier */
+ int n, /* Length of zMod in bytes */
+ DateTime *p /* The date/time value to be modified */
+){
int rc = 1;
- int n;
double r;
- char *z, zBuf[30];
- z = zBuf;
- for(n=0; niJD += localtimeOffset(p, pCtx, &rc);
clearYMD_HMS_TZ(p);
@@ -19182,16 +20239,21 @@ static int parseModifier(sqlite3_context *pCtx, const char *zMod, DateTime *p){
/*
** unixepoch
**
- ** Treat the current value of p->iJD as the number of
+ ** Treat the current value of p->s as the number of
** seconds since 1970. Convert to a real julian day number.
*/
- if( strcmp(z, "unixepoch")==0 && p->validJD ){
- p->iJD = (p->iJD + 43200)/86400 + 21086676*(i64)10000000;
- clearYMD_HMS_TZ(p);
- rc = 0;
+ if( sqlite3_stricmp(z, "unixepoch")==0 && p->rawS ){
+ r = p->s*1000.0 + 210866760000000.0;
+ if( r>=0.0 && r<464269060800000.0 ){
+ clearYMD_HMS_TZ(p);
+ p->iJD = (sqlite3_int64)r;
+ p->validJD = 1;
+ p->rawS = 0;
+ rc = 0;
+ }
}
#ifndef SQLITE_OMIT_LOCALTIME
- else if( strcmp(z, "utc")==0 ){
+ else if( sqlite3_stricmp(z, "utc")==0 && sqlite3NotPureFunc(pCtx) ){
if( p->tzSet==0 ){
sqlite3_int64 c1;
computeJD(p);
@@ -19217,7 +20279,7 @@ static int parseModifier(sqlite3_context *pCtx, const char *zMod, DateTime *p){
** weekday N where 0==Sunday, 1==Monday, and so forth. If the
** date is already on the appropriate weekday, this is a no-op.
*/
- if( strncmp(z, "weekday ", 8)==0
+ if( sqlite3_strnicmp(z, "weekday ", 8)==0
&& sqlite3AtoF(&z[8], &r, sqlite3Strlen30(&z[8]), SQLITE_UTF8)
&& (n=(int)r)==r && n>=0 && r<7 ){
sqlite3_int64 Z;
@@ -19240,23 +20302,24 @@ static int parseModifier(sqlite3_context *pCtx, const char *zMod, DateTime *p){
** Move the date backwards to the beginning of the current day,
** or month or year.
*/
- if( strncmp(z, "start of ", 9)!=0 ) break;
+ if( sqlite3_strnicmp(z, "start of ", 9)!=0 ) break;
+ if( !p->validJD && !p->validYMD && !p->validHMS ) break;
z += 9;
computeYMD(p);
p->validHMS = 1;
p->h = p->m = 0;
p->s = 0.0;
+ p->rawS = 0;
p->validTZ = 0;
p->validJD = 0;
- if( strcmp(z,"month")==0 ){
+ if( sqlite3_stricmp(z,"month")==0 ){
p->D = 1;
rc = 0;
- }else if( strcmp(z,"year")==0 ){
- computeYMD(p);
+ }else if( sqlite3_stricmp(z,"year")==0 ){
p->M = 1;
p->D = 1;
rc = 0;
- }else if( strcmp(z,"day")==0 ){
+ }else if( sqlite3_stricmp(z,"day")==0 ){
rc = 0;
}
break;
@@ -19274,6 +20337,7 @@ static int parseModifier(sqlite3_context *pCtx, const char *zMod, DateTime *p){
case '8':
case '9': {
double rRounder;
+ int i;
for(n=1; z[n] && z[n]!=':' && !sqlite3Isspace(z[n]); n++){}
if( !sqlite3AtoF(z, &r, n, SQLITE_UTF8) ){
rc = 1;
@@ -19302,46 +20366,48 @@ static int parseModifier(sqlite3_context *pCtx, const char *zMod, DateTime *p){
rc = 0;
break;
}
+
+ /* If control reaches this point, it means the transformation is
+ ** one of the forms like "+NNN days". */
z += n;
while( sqlite3Isspace(*z) ) z++;
n = sqlite3Strlen30(z);
if( n>10 || n<3 ) break;
- if( z[n-1]=='s' ){ z[n-1] = 0; n--; }
+ if( sqlite3UpperToLower[(u8)z[n-1]]=='s' ) n--;
computeJD(p);
- rc = 0;
+ rc = 1;
rRounder = r<0 ? -0.5 : +0.5;
- if( n==3 && strcmp(z,"day")==0 ){
- p->iJD += (sqlite3_int64)(r*86400000.0 + rRounder);
- }else if( n==4 && strcmp(z,"hour")==0 ){
- p->iJD += (sqlite3_int64)(r*(86400000.0/24.0) + rRounder);
- }else if( n==6 && strcmp(z,"minute")==0 ){
- p->iJD += (sqlite3_int64)(r*(86400000.0/(24.0*60.0)) + rRounder);
- }else if( n==6 && strcmp(z,"second")==0 ){
- p->iJD += (sqlite3_int64)(r*(86400000.0/(24.0*60.0*60.0)) + rRounder);
- }else if( n==5 && strcmp(z,"month")==0 ){
- int x, y;
- computeYMD_HMS(p);
- p->M += (int)r;
- x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12;
- p->Y += x;
- p->M -= x*12;
- p->validJD = 0;
- computeJD(p);
- y = (int)r;
- if( y!=r ){
- p->iJD += (sqlite3_int64)((r - y)*30.0*86400000.0 + rRounder);
- }
- }else if( n==4 && strcmp(z,"year")==0 ){
- int y = (int)r;
- computeYMD_HMS(p);
- p->Y += y;
- p->validJD = 0;
- computeJD(p);
- if( y!=r ){
- p->iJD += (sqlite3_int64)((r - y)*365.0*86400000.0 + rRounder);
+ for(i=0; i-aXformType[i].rLimit && rM += (int)r;
+ x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12;
+ p->Y += x;
+ p->M -= x*12;
+ p->validJD = 0;
+ r -= (int)r;
+ break;
+ }
+ case 2: { /* Special processing to add years */
+ int y = (int)r;
+ computeYMD_HMS(p);
+ p->Y += y;
+ p->validJD = 0;
+ r -= (int)r;
+ break;
+ }
+ }
+ computeJD(p);
+ p->iJD += (sqlite3_int64)(r*aXformType[i].rXform + rRounder);
+ rc = 0;
+ break;
}
- }else{
- rc = 1;
}
clearYMD_HMS_TZ(p);
break;
@@ -19368,7 +20434,7 @@ static int isDate(
sqlite3_value **argv,
DateTime *p
){
- int i;
+ int i, n;
const unsigned char *z;
int eType;
memset(p, 0, sizeof(*p));
@@ -19377,8 +20443,7 @@ static int isDate(
}
if( (eType = sqlite3_value_type(argv[0]))==SQLITE_FLOAT
|| eType==SQLITE_INTEGER ){
- p->iJD = (sqlite3_int64)(sqlite3_value_double(argv[0])*86400000.0 + 0.5);
- p->validJD = 1;
+ setRawDateNumber(p, sqlite3_value_double(argv[0]));
}else{
z = sqlite3_value_text(argv[0]);
if( !z || parseDateOrTime(context, (char*)z, p) ){
@@ -19387,8 +20452,11 @@ static int isDate(
}
for(i=1; iisError || !validJulianDay(p->iJD) ) return 1;
return 0;
}
@@ -19721,11 +20789,11 @@ static void currentTimeFunc(
SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void){
static FuncDef aDateTimeFuncs[] = {
#ifndef SQLITE_OMIT_DATETIME_FUNCS
- DFUNCTION(julianday, -1, 0, 0, juliandayFunc ),
- DFUNCTION(date, -1, 0, 0, dateFunc ),
- DFUNCTION(time, -1, 0, 0, timeFunc ),
- DFUNCTION(datetime, -1, 0, 0, datetimeFunc ),
- DFUNCTION(strftime, -1, 0, 0, strftimeFunc ),
+ PURE_DATE(julianday, -1, 0, 0, juliandayFunc ),
+ PURE_DATE(date, -1, 0, 0, dateFunc ),
+ PURE_DATE(time, -1, 0, 0, timeFunc ),
+ PURE_DATE(datetime, -1, 0, 0, datetimeFunc ),
+ PURE_DATE(strftime, -1, 0, 0, strftimeFunc ),
DFUNCTION(current_time, 0, 0, 0, ctimeFunc ),
DFUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc),
DFUNCTION(current_date, 0, 0, 0, cdateFunc ),
@@ -19840,7 +20908,7 @@ SQLITE_PRIVATE int sqlite3OsTruncate(sqlite3_file *id, i64 size){
}
SQLITE_PRIVATE int sqlite3OsSync(sqlite3_file *id, int flags){
DO_OS_MALLOC_TEST(id);
- return id->pMethods->xSync(id, flags);
+ return flags ? id->pMethods->xSync(id, flags) : SQLITE_OK;
}
SQLITE_PRIVATE int sqlite3OsFileSize(sqlite3_file *id, i64 *pSize){
DO_OS_MALLOC_TEST(id);
@@ -19895,6 +20963,7 @@ SQLITE_PRIVATE int sqlite3OsSectorSize(sqlite3_file *id){
SQLITE_PRIVATE int sqlite3OsDeviceCharacteristics(sqlite3_file *id){
return id->pMethods->xDeviceCharacteristics(id);
}
+#ifndef SQLITE_OMIT_WAL
SQLITE_PRIVATE int sqlite3OsShmLock(sqlite3_file *id, int offset, int n, int flags){
return id->pMethods->xShmLock(id, offset, n, flags);
}
@@ -19914,6 +20983,7 @@ SQLITE_PRIVATE int sqlite3OsShmMap(
DO_OS_MALLOC_TEST(id);
return id->pMethods->xShmMap(id, iPage, pgsz, bExtend, pp);
}
+#endif /* SQLITE_OMIT_WAL */
#if SQLITE_MAX_MMAP_SIZE>0
/* The real implementation of xFetch and xUnfetch */
@@ -20186,7 +21256,7 @@ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){
/* #include "sqliteInt.h" */
-#ifndef SQLITE_OMIT_BUILTIN_TEST
+#ifndef SQLITE_UNTESTABLE
/*
** Global variables.
@@ -20244,7 +21314,7 @@ SQLITE_PRIVATE void sqlite3EndBenignMalloc(void){
}
}
-#endif /* #ifndef SQLITE_OMIT_BUILTIN_TEST */
+#endif /* #ifndef SQLITE_UNTESTABLE */
/************** End of fault.c ***********************************************/
/************** Begin file mem0.c ********************************************/
@@ -20369,7 +21439,9 @@ SQLITE_PRIVATE void sqlite3MemSetDefault(void){
*/
#include
#include
+#ifdef SQLITE_MIGHT_BE_SINGLE_CORE
#include
+#endif /* SQLITE_MIGHT_BE_SINGLE_CORE */
static malloc_zone_t* _sqliteZone_;
#define SQLITE_MALLOC(x) malloc_zone_malloc(_sqliteZone_, (x))
#define SQLITE_FREE(x) malloc_zone_free(_sqliteZone_, (x));
@@ -20437,7 +21509,9 @@ static malloc_zone_t* _sqliteZone_;
*/
static void *sqlite3MemMalloc(int nByte){
#ifdef SQLITE_MALLOCSIZE
- void *p = SQLITE_MALLOC( nByte );
+ void *p;
+ testcase( ROUND8(nByte)==nByte );
+ p = SQLITE_MALLOC( nByte );
if( p==0 ){
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
@@ -20446,7 +21520,7 @@ static void *sqlite3MemMalloc(int nByte){
#else
sqlite3_int64 *p;
assert( nByte>0 );
- nByte = ROUND8(nByte);
+ testcase( ROUND8(nByte)!=nByte );
p = SQLITE_MALLOC( nByte+8 );
if( p ){
p[0] = nByte;
@@ -20560,19 +21634,10 @@ static int sqlite3MemInit(void *NotUsed){
}else{
/* only 1 core, use our own zone to contention over global locks,
** e.g. we have our own dedicated locks */
- bool success;
- malloc_zone_t* newzone = malloc_create_zone(4096, 0);
- malloc_set_zone_name(newzone, "Sqlite_Heap");
- do{
- success = OSAtomicCompareAndSwapPtrBarrier(NULL, newzone,
- (void * volatile *)&_sqliteZone_);
- }while(!_sqliteZone_);
- if( !success ){
- /* somebody registered a zone first */
- malloc_destroy_zone(newzone);
- }
+ _sqliteZone_ = malloc_create_zone(4096, 0);
+ malloc_set_zone_name(_sqliteZone_, "Sqlite_Heap");
}
-#endif
+#endif /* defined(__APPLE__) && !defined(SQLITE_WITHOUT_ZONEMALLOC) */
UNUSED_PARAMETER(NotUsed);
return SQLITE_OK;
}
@@ -22437,6 +23502,193 @@ static SQLITE_WSD int mutexIsInit = 0;
#ifndef SQLITE_MUTEX_OMIT
+
+#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS
+/*
+** This block (enclosed by SQLITE_ENABLE_MULTITHREADED_CHECKS) contains
+** the implementation of a wrapper around the system default mutex
+** implementation (sqlite3DefaultMutex()).
+**
+** Most calls are passed directly through to the underlying default
+** mutex implementation. Except, if a mutex is configured by calling
+** sqlite3MutexWarnOnContention() on it, then if contention is ever
+** encountered within xMutexEnter() a warning is emitted via sqlite3_log().
+**
+** This type of mutex is used as the database handle mutex when testing
+** apps that usually use SQLITE_CONFIG_MULTITHREAD mode.
+*/
+
+/*
+** Type for all mutexes used when SQLITE_ENABLE_MULTITHREADED_CHECKS
+** is defined. Variable CheckMutex.mutex is a pointer to the real mutex
+** allocated by the system mutex implementation. Variable iType is usually set
+** to the type of mutex requested - SQLITE_MUTEX_RECURSIVE, SQLITE_MUTEX_FAST
+** or one of the static mutex identifiers. Or, if this is a recursive mutex
+** that has been configured using sqlite3MutexWarnOnContention(), it is
+** set to SQLITE_MUTEX_WARNONCONTENTION.
+*/
+typedef struct CheckMutex CheckMutex;
+struct CheckMutex {
+ int iType;
+ sqlite3_mutex *mutex;
+};
+
+#define SQLITE_MUTEX_WARNONCONTENTION (-1)
+
+/*
+** Pointer to real mutex methods object used by the CheckMutex
+** implementation. Set by checkMutexInit().
+*/
+static SQLITE_WSD const sqlite3_mutex_methods *pGlobalMutexMethods;
+
+#ifdef SQLITE_DEBUG
+static int checkMutexHeld(sqlite3_mutex *p){
+ return pGlobalMutexMethods->xMutexHeld(((CheckMutex*)p)->mutex);
+}
+static int checkMutexNotheld(sqlite3_mutex *p){
+ return pGlobalMutexMethods->xMutexNotheld(((CheckMutex*)p)->mutex);
+}
+#endif
+
+/*
+** Initialize and deinitialize the mutex subsystem.
+*/
+static int checkMutexInit(void){
+ pGlobalMutexMethods = sqlite3DefaultMutex();
+ return SQLITE_OK;
+}
+static int checkMutexEnd(void){
+ pGlobalMutexMethods = 0;
+ return SQLITE_OK;
+}
+
+/*
+** Allocate a mutex.
+*/
+static sqlite3_mutex *checkMutexAlloc(int iType){
+ static CheckMutex staticMutexes[] = {
+ {2, 0}, {3, 0}, {4, 0}, {5, 0},
+ {6, 0}, {7, 0}, {8, 0}, {9, 0},
+ {10, 0}, {11, 0}, {12, 0}, {13, 0}
+ };
+ CheckMutex *p = 0;
+
+ assert( SQLITE_MUTEX_RECURSIVE==1 && SQLITE_MUTEX_FAST==0 );
+ if( iType<2 ){
+ p = sqlite3MallocZero(sizeof(CheckMutex));
+ if( p==0 ) return 0;
+ p->iType = iType;
+ }else{
+#ifdef SQLITE_ENABLE_API_ARMOR
+ if( iType-2>=ArraySize(staticMutexes) ){
+ (void)SQLITE_MISUSE_BKPT;
+ return 0;
+ }
+#endif
+ p = &staticMutexes[iType-2];
+ }
+
+ if( p->mutex==0 ){
+ p->mutex = pGlobalMutexMethods->xMutexAlloc(iType);
+ if( p->mutex==0 ){
+ if( iType<2 ){
+ sqlite3_free(p);
+ }
+ p = 0;
+ }
+ }
+
+ return (sqlite3_mutex*)p;
+}
+
+/*
+** Free a mutex.
+*/
+static void checkMutexFree(sqlite3_mutex *p){
+ assert( SQLITE_MUTEX_RECURSIVE<2 );
+ assert( SQLITE_MUTEX_FAST<2 );
+ assert( SQLITE_MUTEX_WARNONCONTENTION<2 );
+
+#if SQLITE_ENABLE_API_ARMOR
+ if( ((CheckMutex*)p)->iType<2 )
+#endif
+ {
+ CheckMutex *pCheck = (CheckMutex*)p;
+ pGlobalMutexMethods->xMutexFree(pCheck->mutex);
+ sqlite3_free(pCheck);
+ }
+#ifdef SQLITE_ENABLE_API_ARMOR
+ else{
+ (void)SQLITE_MISUSE_BKPT;
+ }
+#endif
+}
+
+/*
+** Enter the mutex.
+*/
+static void checkMutexEnter(sqlite3_mutex *p){
+ CheckMutex *pCheck = (CheckMutex*)p;
+ if( pCheck->iType==SQLITE_MUTEX_WARNONCONTENTION ){
+ if( SQLITE_OK==pGlobalMutexMethods->xMutexTry(pCheck->mutex) ){
+ return;
+ }
+ sqlite3_log(SQLITE_MISUSE,
+ "illegal multi-threaded access to database connection"
+ );
+ }
+ pGlobalMutexMethods->xMutexEnter(pCheck->mutex);
+}
+
+/*
+** Enter the mutex (do not block).
+*/
+static int checkMutexTry(sqlite3_mutex *p){
+ CheckMutex *pCheck = (CheckMutex*)p;
+ return pGlobalMutexMethods->xMutexTry(pCheck->mutex);
+}
+
+/*
+** Leave the mutex.
+*/
+static void checkMutexLeave(sqlite3_mutex *p){
+ CheckMutex *pCheck = (CheckMutex*)p;
+ pGlobalMutexMethods->xMutexLeave(pCheck->mutex);
+}
+
+sqlite3_mutex_methods const *multiThreadedCheckMutex(void){
+ static const sqlite3_mutex_methods sMutex = {
+ checkMutexInit,
+ checkMutexEnd,
+ checkMutexAlloc,
+ checkMutexFree,
+ checkMutexEnter,
+ checkMutexTry,
+ checkMutexLeave,
+#ifdef SQLITE_DEBUG
+ checkMutexHeld,
+ checkMutexNotheld
+#else
+ 0,
+ 0
+#endif
+ };
+ return &sMutex;
+}
+
+/*
+** Mark the SQLITE_MUTEX_RECURSIVE mutex passed as the only argument as
+** one on which there should be no contention.
+*/
+SQLITE_PRIVATE void sqlite3MutexWarnOnContention(sqlite3_mutex *p){
+ if( sqlite3GlobalConfig.mutex.xMutexAlloc==checkMutexAlloc ){
+ CheckMutex *pCheck = (CheckMutex*)p;
+ assert( pCheck->iType==SQLITE_MUTEX_RECURSIVE );
+ pCheck->iType = SQLITE_MUTEX_WARNONCONTENTION;
+ }
+}
+#endif /* ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS */
+
/*
** Initialize the mutex system.
*/
@@ -22452,7 +23704,11 @@ SQLITE_PRIVATE int sqlite3MutexInit(void){
sqlite3_mutex_methods *pTo = &sqlite3GlobalConfig.mutex;
if( sqlite3GlobalConfig.bCoreMutex ){
+#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS
+ pFrom = multiThreadedCheckMutex();
+#else
pFrom = sqlite3DefaultMutex();
+#endif
}else{
pFrom = sqlite3NoopMutex();
}
@@ -22579,6 +23835,7 @@ SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex *p){
#endif /* !defined(SQLITE_MUTEX_OMIT) */
+
/************** End of mutex.c ***********************************************/
/************** Begin file mutex_noop.c **************************************/
/*
@@ -23568,8 +24825,7 @@ SQLITE_PRIVATE void sqlite3MemoryBarrier(void){
SQLITE_MEMORY_BARRIER;
#elif defined(__GNUC__)
__sync_synchronize();
-#elif !defined(SQLITE_DISABLE_INTRINSIC) && \
- defined(_MSC_VER) && _MSC_VER>=1300
+#elif MSVC_VERSION>=1300
_ReadWriteBarrier();
#elif defined(MemoryBarrier)
MemoryBarrier();
@@ -23780,8 +25036,8 @@ static void winMutexEnter(sqlite3_mutex *p){
p->owner = tid;
p->nRef++;
if( p->trace ){
- OSTRACE(("ENTER-MUTEX tid=%lu, mutex=%p (%d), nRef=%d\n",
- tid, p, p->trace, p->nRef));
+ OSTRACE(("ENTER-MUTEX tid=%lu, mutex(%d)=%p (%d), nRef=%d\n",
+ tid, p->id, p, p->trace, p->nRef));
}
#endif
}
@@ -23823,8 +25079,8 @@ static int winMutexTry(sqlite3_mutex *p){
#endif
#ifdef SQLITE_DEBUG
if( p->trace ){
- OSTRACE(("TRY-MUTEX tid=%lu, mutex=%p (%d), owner=%lu, nRef=%d, rc=%s\n",
- tid, p, p->trace, p->owner, p->nRef, sqlite3ErrName(rc)));
+ OSTRACE(("TRY-MUTEX tid=%lu, mutex(%d)=%p (%d), owner=%lu, nRef=%d, rc=%s\n",
+ tid, p->id, p, p->trace, p->owner, p->nRef, sqlite3ErrName(rc)));
}
#endif
return rc;
@@ -23852,8 +25108,8 @@ static void winMutexLeave(sqlite3_mutex *p){
LeaveCriticalSection(&p->mutex);
#ifdef SQLITE_DEBUG
if( p->trace ){
- OSTRACE(("LEAVE-MUTEX tid=%lu, mutex=%p (%d), nRef=%d\n",
- tid, p, p->trace, p->nRef));
+ OSTRACE(("LEAVE-MUTEX tid=%lu, mutex(%d)=%p (%d), nRef=%d\n",
+ tid, p->id, p, p->trace, p->nRef));
}
#endif
}
@@ -23916,14 +25172,6 @@ SQLITE_API int sqlite3_release_memory(int n){
#endif
}
-/*
-** An instance of the following object records the location of
-** each unused scratch buffer.
-*/
-typedef struct ScratchFreeslot {
- struct ScratchFreeslot *pNext; /* Next unused scratch buffer */
-} ScratchFreeslot;
-
/*
** State information local to the memory allocation subsystem.
*/
@@ -23931,22 +25179,12 @@ static SQLITE_WSD struct Mem0Global {
sqlite3_mutex *mutex; /* Mutex to serialize access */
sqlite3_int64 alarmThreshold; /* The soft heap limit */
- /*
- ** Pointers to the end of sqlite3GlobalConfig.pScratch memory
- ** (so that a range test can be used to determine if an allocation
- ** being freed came from pScratch) and a pointer to the list of
- ** unused scratch allocations.
- */
- void *pScratchEnd;
- ScratchFreeslot *pScratchFree;
- u32 nScratchFree;
-
/*
** True if heap is nearly "full" where "full" is defined by the
** sqlite3_soft_heap_limit() setting.
*/
int nearlyFull;
-} mem0 = { 0, 0, 0, 0, 0, 0 };
+} mem0 = { 0, 0, 0 };
#define mem0 GLOBAL(struct Mem0Global, mem0)
@@ -24016,28 +25254,6 @@ SQLITE_PRIVATE int sqlite3MallocInit(void){
}
memset(&mem0, 0, sizeof(mem0));
mem0.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
- if( sqlite3GlobalConfig.pScratch && sqlite3GlobalConfig.szScratch>=100
- && sqlite3GlobalConfig.nScratch>0 ){
- int i, n, sz;
- ScratchFreeslot *pSlot;
- sz = ROUNDDOWN8(sqlite3GlobalConfig.szScratch);
- sqlite3GlobalConfig.szScratch = sz;
- pSlot = (ScratchFreeslot*)sqlite3GlobalConfig.pScratch;
- n = sqlite3GlobalConfig.nScratch;
- mem0.pScratchFree = pSlot;
- mem0.nScratchFree = n;
- for(i=0; ipNext = (ScratchFreeslot*)(sz+(char*)pSlot);
- pSlot = pSlot->pNext;
- }
- pSlot->pNext = 0;
- mem0.pScratchEnd = (void*)&pSlot[1];
- }else{
- mem0.pScratchEnd = 0;
- sqlite3GlobalConfig.pScratch = 0;
- sqlite3GlobalConfig.szScratch = 0;
- sqlite3GlobalConfig.nScratch = 0;
- }
if( sqlite3GlobalConfig.pPage==0 || sqlite3GlobalConfig.szPage<512
|| sqlite3GlobalConfig.nPage<=0 ){
sqlite3GlobalConfig.pPage = 0;
@@ -24101,11 +25317,26 @@ static void sqlite3MallocAlarm(int nByte){
** Do a memory allocation with statistics and alarms. Assume the
** lock is already held.
*/
-static int mallocWithAlarm(int n, void **pp){
- int nFull;
+static void mallocWithAlarm(int n, void **pp){
void *p;
+ int nFull;
assert( sqlite3_mutex_held(mem0.mutex) );
+ assert( n>0 );
+
+ /* In Firefox (circa 2017-02-08), xRoundup() is remapped to an internal
+ ** implementation of malloc_good_size(), which must be called in debug
+ ** mode and specifically when the DMD "Dark Matter Detector" is enabled
+ ** or else a crash results. Hence, do not attempt to optimize out the
+ ** following xRoundup() call. */
nFull = sqlite3GlobalConfig.m.xRoundup(n);
+
+#ifdef SQLITE_MAX_MEMORY
+ if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED)+nFull>SQLITE_MAX_MEMORY ){
+ *pp = 0;
+ return;
+ }
+#endif
+
sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, n);
if( mem0.alarmThreshold>0 ){
sqlite3_int64 nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
@@ -24129,7 +25360,6 @@ static int mallocWithAlarm(int n, void **pp){
sqlite3StatusUp(SQLITE_STATUS_MALLOC_COUNT, 1);
}
*pp = p;
- return nFull;
}
/*
@@ -24174,105 +25404,6 @@ SQLITE_API void *sqlite3_malloc64(sqlite3_uint64 n){
return sqlite3Malloc(n);
}
-/*
-** Each thread may only have a single outstanding allocation from
-** xScratchMalloc(). We verify this constraint in the single-threaded
-** case by setting scratchAllocOut to 1 when an allocation
-** is outstanding clearing it when the allocation is freed.
-*/
-#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
-static int scratchAllocOut = 0;
-#endif
-
-
-/*
-** Allocate memory that is to be used and released right away.
-** This routine is similar to alloca() in that it is not intended
-** for situations where the memory might be held long-term. This
-** routine is intended to get memory to old large transient data
-** structures that would not normally fit on the stack of an
-** embedded processor.
-*/
-SQLITE_PRIVATE void *sqlite3ScratchMalloc(int n){
- void *p;
- assert( n>0 );
-
- sqlite3_mutex_enter(mem0.mutex);
- sqlite3StatusHighwater(SQLITE_STATUS_SCRATCH_SIZE, n);
- if( mem0.nScratchFree && sqlite3GlobalConfig.szScratch>=n ){
- p = mem0.pScratchFree;
- mem0.pScratchFree = mem0.pScratchFree->pNext;
- mem0.nScratchFree--;
- sqlite3StatusUp(SQLITE_STATUS_SCRATCH_USED, 1);
- sqlite3_mutex_leave(mem0.mutex);
- }else{
- sqlite3_mutex_leave(mem0.mutex);
- p = sqlite3Malloc(n);
- if( sqlite3GlobalConfig.bMemstat && p ){
- sqlite3_mutex_enter(mem0.mutex);
- sqlite3StatusUp(SQLITE_STATUS_SCRATCH_OVERFLOW, sqlite3MallocSize(p));
- sqlite3_mutex_leave(mem0.mutex);
- }
- sqlite3MemdebugSetType(p, MEMTYPE_SCRATCH);
- }
- assert( sqlite3_mutex_notheld(mem0.mutex) );
-
-
-#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
- /* EVIDENCE-OF: R-12970-05880 SQLite will not use more than one scratch
- ** buffers per thread.
- **
- ** This can only be checked in single-threaded mode.
- */
- assert( scratchAllocOut==0 );
- if( p ) scratchAllocOut++;
-#endif
-
- return p;
-}
-SQLITE_PRIVATE void sqlite3ScratchFree(void *p){
- if( p ){
-
-#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
- /* Verify that no more than two scratch allocation per thread
- ** is outstanding at one time. (This is only checked in the
- ** single-threaded case since checking in the multi-threaded case
- ** would be much more complicated.) */
- assert( scratchAllocOut>=1 && scratchAllocOut<=2 );
- scratchAllocOut--;
-#endif
-
- if( SQLITE_WITHIN(p, sqlite3GlobalConfig.pScratch, mem0.pScratchEnd) ){
- /* Release memory from the SQLITE_CONFIG_SCRATCH allocation */
- ScratchFreeslot *pSlot;
- pSlot = (ScratchFreeslot*)p;
- sqlite3_mutex_enter(mem0.mutex);
- pSlot->pNext = mem0.pScratchFree;
- mem0.pScratchFree = pSlot;
- mem0.nScratchFree++;
- assert( mem0.nScratchFree <= (u32)sqlite3GlobalConfig.nScratch );
- sqlite3StatusDown(SQLITE_STATUS_SCRATCH_USED, 1);
- sqlite3_mutex_leave(mem0.mutex);
- }else{
- /* Release memory back to the heap */
- assert( sqlite3MemdebugHasType(p, MEMTYPE_SCRATCH) );
- assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_SCRATCH) );
- sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
- if( sqlite3GlobalConfig.bMemstat ){
- int iSize = sqlite3MallocSize(p);
- sqlite3_mutex_enter(mem0.mutex);
- sqlite3StatusDown(SQLITE_STATUS_SCRATCH_OVERFLOW, iSize);
- sqlite3StatusDown(SQLITE_STATUS_MEMORY_USED, iSize);
- sqlite3StatusDown(SQLITE_STATUS_MALLOC_COUNT, 1);
- sqlite3GlobalConfig.m.xFree(p);
- sqlite3_mutex_leave(mem0.mutex);
- }else{
- sqlite3GlobalConfig.m.xFree(p);
- }
- }
- }
-}
-
/*
** TRUE if p is a lookaside memory allocation from db
*/
@@ -24295,7 +25426,7 @@ SQLITE_PRIVATE int sqlite3MallocSize(void *p){
SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, void *p){
assert( p!=0 );
if( db==0 || !isLookaside(db,p) ){
-#if SQLITE_DEBUG
+#ifdef SQLITE_DEBUG
if( db==0 ){
assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
@@ -24344,11 +25475,12 @@ static SQLITE_NOINLINE void measureAllocationSize(sqlite3 *db, void *p){
/*
** Free memory that might be associated with a particular database
-** connection.
+** connection. Calling sqlite3DbFree(D,X) for X==0 is a harmless no-op.
+** The sqlite3DbFreeNN(D,X) version requires that X be non-NULL.
*/
-SQLITE_PRIVATE void sqlite3DbFree(sqlite3 *db, void *p){
+SQLITE_PRIVATE void sqlite3DbFreeNN(sqlite3 *db, void *p){
assert( db==0 || sqlite3_mutex_held(db->mutex) );
- if( p==0 ) return;
+ assert( p!=0 );
if( db ){
if( db->pnBytesFreed ){
measureAllocationSize(db, p);
@@ -24356,13 +25488,12 @@ SQLITE_PRIVATE void sqlite3DbFree(sqlite3 *db, void *p){
}
if( isLookaside(db, p) ){
LookasideSlot *pBuf = (LookasideSlot*)p;
-#if SQLITE_DEBUG
+#ifdef SQLITE_DEBUG
/* Trash all content in the buffer being freed */
memset(p, 0xaa, db->lookaside.sz);
#endif
pBuf->pNext = db->lookaside.pFree;
db->lookaside.pFree = pBuf;
- db->lookaside.nOut--;
return;
}
}
@@ -24372,6 +25503,10 @@ SQLITE_PRIVATE void sqlite3DbFree(sqlite3 *db, void *p){
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
sqlite3_free(p);
}
+SQLITE_PRIVATE void sqlite3DbFree(sqlite3 *db, void *p){
+ assert( db==0 || sqlite3_mutex_held(db->mutex) );
+ if( p ) sqlite3DbFreeNN(db, p);
+}
/*
** Change the size of an existing memory allocation
@@ -24403,7 +25538,7 @@ SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, u64 nBytes){
sqlite3_mutex_enter(mem0.mutex);
sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, (int)nBytes);
nDiff = nNew - nOld;
- if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >=
+ if( nDiff>0 && sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >=
mem0.alarmThreshold-nDiff ){
sqlite3MallocAlarm(nDiff);
}
@@ -24519,16 +25654,16 @@ SQLITE_PRIVATE void *sqlite3DbMallocRawNN(sqlite3 *db, u64 n){
assert( db->mallocFailed==0 );
if( n>db->lookaside.sz ){
db->lookaside.anStat[1]++;
- }else if( (pBuf = db->lookaside.pFree)==0 ){
- db->lookaside.anStat[2]++;
- }else{
+ }else if( (pBuf = db->lookaside.pFree)!=0 ){
db->lookaside.pFree = pBuf->pNext;
- db->lookaside.nOut++;
db->lookaside.anStat[0]++;
- if( db->lookaside.nOut>db->lookaside.mxOut ){
- db->lookaside.mxOut = db->lookaside.nOut;
- }
return (void*)pBuf;
+ }else if( (pBuf = db->lookaside.pInit)!=0 ){
+ db->lookaside.pInit = pBuf->pNext;
+ db->lookaside.anStat[0]++;
+ return (void*)pBuf;
+ }else{
+ db->lookaside.anStat[2]++;
}
}else if( db->mallocFailed ){
return 0;
@@ -24610,9 +25745,8 @@ SQLITE_PRIVATE char *sqlite3DbStrDup(sqlite3 *db, const char *z){
if( z==0 ){
return 0;
}
- n = sqlite3Strlen30(z) + 1;
- assert( (n&0x7fffffff)==n );
- zNew = sqlite3DbMallocRaw(db, (int)n);
+ n = strlen(z) + 1;
+ zNew = sqlite3DbMallocRaw(db, n);
if( zNew ){
memcpy(zNew, z, n);
}
@@ -24633,6 +25767,19 @@ SQLITE_PRIVATE char *sqlite3DbStrNDup(sqlite3 *db, const char *z, u64 n){
return zNew;
}
+/*
+** The text between zStart and zEnd represents a phrase within a larger
+** SQL statement. Make a copy of this phrase in space obtained form
+** sqlite3DbMalloc(). Omit leading and trailing whitespace.
+*/
+SQLITE_PRIVATE char *sqlite3DbSpanDup(sqlite3 *db, const char *zStart, const char *zEnd){
+ int n;
+ while( sqlite3Isspace(zStart[0]) ) zStart++;
+ n = (int)(zEnd - zStart);
+ while( ALWAYS(n>0) && sqlite3Isspace(zStart[n-1]) ) n--;
+ return sqlite3DbStrNDup(db, zStart, n);
+}
+
/*
** Free any prior content in *pz and replace it with a copy of zNew.
*/
@@ -24726,7 +25873,7 @@ SQLITE_PRIVATE int sqlite3ApiExit(sqlite3* db, int rc){
** Conversion types fall into various categories as defined by the
** following enumeration.
*/
-#define etRADIX 0 /* Integer types. %d, %x, %o, and so forth */
+#define etRADIX 0 /* non-decimal integer types. %x %o */
#define etFLOAT 1 /* Floating point. %f */
#define etEXP 2 /* Exponentional notation. %e and %E */
#define etGENERIC 3 /* Floating or exponential, depending on exponent. %g */
@@ -24744,8 +25891,9 @@ SQLITE_PRIVATE int sqlite3ApiExit(sqlite3* db, int rc){
#define etPOINTER 13 /* The %p conversion */
#define etSQLESCAPE3 14 /* %w -> Strings with '\"' doubled */
#define etORDINAL 15 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */
+#define etDECIMAL 16 /* %d or %u, but not %x, %o */
-#define etINVALID 16 /* Any unrecognized conversion type */
+#define etINVALID 17 /* Any unrecognized conversion type */
/*
@@ -24769,9 +25917,8 @@ typedef struct et_info { /* Information about each format field */
/*
** Allowed values for et_info.flags
*/
-#define FLAG_SIGNED 1 /* True if the value to convert is signed */
-#define FLAG_INTERN 2 /* True if for internal use only */
-#define FLAG_STRING 4 /* Allow infinity precision */
+#define FLAG_SIGNED 1 /* True if the value to convert is signed */
+#define FLAG_STRING 4 /* Allow infinite precision */
/*
@@ -24781,7 +25928,7 @@ typedef struct et_info { /* Information about each format field */
static const char aDigits[] = "0123456789ABCDEF0123456789abcdef";
static const char aPrefix[] = "-x0\000X0";
static const et_info fmtinfo[] = {
- { 'd', 10, 1, etRADIX, 0, 0 },
+ { 'd', 10, 1, etDECIMAL, 0, 0 },
{ 's', 0, 4, etSTRING, 0, 0 },
{ 'g', 0, 1, etGENERIC, 30, 0 },
{ 'z', 0, 4, etDYNSTRING, 0, 0 },
@@ -24790,7 +25937,7 @@ static const et_info fmtinfo[] = {
{ 'w', 0, 4, etSQLESCAPE3, 0, 0 },
{ 'c', 0, 0, etCHARX, 0, 0 },
{ 'o', 8, 0, etRADIX, 0, 2 },
- { 'u', 10, 0, etRADIX, 0, 0 },
+ { 'u', 10, 0, etDECIMAL, 0, 0 },
{ 'x', 16, 0, etRADIX, 16, 1 },
{ 'X', 16, 0, etRADIX, 0, 4 },
#ifndef SQLITE_OMIT_FLOATING_POINT
@@ -24799,16 +25946,15 @@ static const et_info fmtinfo[] = {
{ 'E', 0, 1, etEXP, 14, 0 },
{ 'G', 0, 1, etGENERIC, 14, 0 },
#endif
- { 'i', 10, 1, etRADIX, 0, 0 },
+ { 'i', 10, 1, etDECIMAL, 0, 0 },
{ 'n', 0, 0, etSIZE, 0, 0 },
{ '%', 0, 0, etPERCENT, 0, 0 },
{ 'p', 16, 0, etPOINTER, 0, 1 },
-/* All the rest have the FLAG_INTERN bit set and are thus for internal
-** use only */
- { 'T', 0, 2, etTOKEN, 0, 0 },
- { 'S', 0, 2, etSRCLIST, 0, 0 },
- { 'r', 10, 3, etORDINAL, 0, 0 },
+ /* All the rest are undocumented and are for internal use only */
+ { 'T', 0, 0, etTOKEN, 0, 0 },
+ { 'S', 0, 0, etSRCLIST, 0, 0 },
+ { 'r', 10, 1, etORDINAL, 0, 0 },
};
/*
@@ -24892,17 +26038,15 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
int idx; /* A general purpose loop counter */
int width; /* Width of the current field */
etByte flag_leftjustify; /* True if "-" flag is present */
- etByte flag_plussign; /* True if "+" flag is present */
- etByte flag_blanksign; /* True if " " flag is present */
+ etByte flag_prefix; /* '+' or ' ' or 0 for prefix */
etByte flag_alternateform; /* True if "#" flag is present */
etByte flag_altform2; /* True if "!" flag is present */
etByte flag_zeropad; /* True if field width constant starts with zero */
- etByte flag_long; /* True if "l" flag is present */
- etByte flag_longlong; /* True if the "ll" flag is present */
+ etByte flag_long; /* 1 for the "l" flag, 2 for "ll", 0 by default */
etByte done; /* Loop termination flag */
+ etByte cThousand; /* Thousands separator for %d and %u */
etByte xtype = etINVALID; /* Conversion paradigm */
u8 bArgList; /* True for SQLITE_PRINTF_SQLFUNC */
- u8 useIntern; /* Ok to use internal conversions (ex: %T) */
char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */
sqlite_uint64 longvalue; /* Value for integer types */
LONGDOUBLE_TYPE realvalue; /* Value for real types */
@@ -24921,13 +26065,11 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
char buf[etBUFSIZE]; /* Conversion buffer */
bufpt = 0;
- if( pAccum->printfFlags ){
- if( (bArgList = (pAccum->printfFlags & SQLITE_PRINTF_SQLFUNC))!=0 ){
- pArgList = va_arg(ap, PrintfArguments*);
- }
- useIntern = pAccum->printfFlags & SQLITE_PRINTF_INTERNAL;
+ if( (pAccum->printfFlags & SQLITE_PRINTF_SQLFUNC)!=0 ){
+ pArgList = va_arg(ap, PrintfArguments*);
+ bArgList = 1;
}else{
- bArgList = useIntern = 0;
+ bArgList = 0;
}
for(; (c=(*fmt))!=0; ++fmt){
if( c!='%' ){
@@ -24945,17 +26087,18 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
break;
}
/* Find out what flags are present */
- flag_leftjustify = flag_plussign = flag_blanksign =
+ flag_leftjustify = flag_prefix = cThousand =
flag_alternateform = flag_altform2 = flag_zeropad = 0;
done = 0;
do{
switch( c ){
case '-': flag_leftjustify = 1; break;
- case '+': flag_plussign = 1; break;
- case ' ': flag_blanksign = 1; break;
+ case '+': flag_prefix = '+'; break;
+ case ' ': flag_prefix = ' '; break;
case '#': flag_alternateform = 1; break;
case '!': flag_altform2 = 1; break;
case '0': flag_zeropad = 1; break;
+ case ',': cThousand = ','; break;
default: done = 1; break;
}
}while( !done && (c=(*++fmt))!=0 );
@@ -25025,13 +26168,11 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
flag_long = 1;
c = *++fmt;
if( c=='l' ){
- flag_longlong = 1;
+ flag_long = 2;
c = *++fmt;
- }else{
- flag_longlong = 0;
}
}else{
- flag_long = flag_longlong = 0;
+ flag_long = 0;
}
/* Fetch the info entry for the field */
infop = &fmtinfo[0];
@@ -25039,11 +26180,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
for(idx=0; idxflags & FLAG_INTERN)==0 ){
- xtype = infop->type;
- }else{
- return;
- }
+ xtype = infop->type;
break;
}
}
@@ -25053,15 +26190,11 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
**
** flag_alternateform TRUE if a '#' is present.
** flag_altform2 TRUE if a '!' is present.
- ** flag_plussign TRUE if a '+' is present.
+ ** flag_prefix '+' or ' ' or zero
** flag_leftjustify TRUE if a '-' is present or if the
** field width was negative.
** flag_zeropad TRUE if the width began with 0.
- ** flag_long TRUE if the letter 'l' (ell) prefixed
- ** the conversion character.
- ** flag_longlong TRUE if the letter 'll' (ell ell) prefixed
- ** the conversion character.
- ** flag_blanksign TRUE if a ' ' is present.
+ ** flag_long 1 for "l", 2 for "ll"
** width The specified field width. This is
** always non-negative. Zero is the default.
** precision The specified precision. The default
@@ -25071,19 +26204,24 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
*/
switch( xtype ){
case etPOINTER:
- flag_longlong = sizeof(char*)==sizeof(i64);
- flag_long = sizeof(char*)==sizeof(long int);
+ flag_long = sizeof(char*)==sizeof(i64) ? 2 :
+ sizeof(char*)==sizeof(long int) ? 1 : 0;
/* Fall through into the next case */
case etORDINAL:
- case etRADIX:
+ case etRADIX:
+ cThousand = 0;
+ /* Fall through into the next case */
+ case etDECIMAL:
if( infop->flags & FLAG_SIGNED ){
i64 v;
if( bArgList ){
v = getIntArg(pArgList);
- }else if( flag_longlong ){
- v = va_arg(ap,i64);
}else if( flag_long ){
- v = va_arg(ap,long int);
+ if( flag_long==2 ){
+ v = va_arg(ap,i64) ;
+ }else{
+ v = va_arg(ap,long int);
+ }
}else{
v = va_arg(ap,int);
}
@@ -25096,17 +26234,17 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
prefix = '-';
}else{
longvalue = v;
- if( flag_plussign ) prefix = '+';
- else if( flag_blanksign ) prefix = ' ';
- else prefix = 0;
+ prefix = flag_prefix;
}
}else{
if( bArgList ){
longvalue = (u64)getIntArg(pArgList);
- }else if( flag_longlong ){
- longvalue = va_arg(ap,u64);
}else if( flag_long ){
- longvalue = va_arg(ap,unsigned long int);
+ if( flag_long==2 ){
+ longvalue = va_arg(ap,u64);
+ }else{
+ longvalue = va_arg(ap,unsigned long int);
+ }
}else{
longvalue = va_arg(ap,unsigned int);
}
@@ -25116,16 +26254,17 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
if( flag_zeropad && precision0 );
}
length = (int)(&zOut[nOut-1]-bufpt);
- for(idx=precision-length; idx>0; idx--){
+ while( precision>length ){
*(--bufpt) = '0'; /* Zero pad */
+ length++;
+ }
+ if( cThousand ){
+ int nn = (length - 1)/3; /* Number of "," to insert */
+ int ix = (length - 1)%3 + 1;
+ bufpt -= nn;
+ for(idx=0; nn>0; idx++){
+ bufpt[idx] = bufpt[idx+nn];
+ ix--;
+ if( ix==0 ){
+ bufpt[++idx] = cThousand;
+ nn--;
+ ix = 3;
+ }
+ }
}
if( prefix ) *(--bufpt) = prefix; /* Add sign */
if( flag_alternateform && infop->prefix ){ /* Add "0" or "0x" */
@@ -25174,9 +26328,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
realvalue = -realvalue;
prefix = '-';
}else{
- if( flag_plussign ) prefix = '+';
- else if( flag_blanksign ) prefix = ' ';
- else prefix = 0;
+ prefix = flag_prefix;
}
if( xtype==etGENERIC && precision>0 ) precision--;
testcase( precision>0xfff );
@@ -25362,7 +26514,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
if( precision>=0 ){
for(length=0; lengthprintfFlags & SQLITE_PRINTF_INTERNAL)==0 ) return;
+ pToken = va_arg(ap, Token*);
assert( bArgList==0 );
if( pToken && pToken->n ){
sqlite3StrAccumAppend(pAccum, (const char*)pToken->z, pToken->n);
@@ -25421,9 +26575,13 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
break;
}
case etSRCLIST: {
- SrcList *pSrc = va_arg(ap, SrcList*);
- int k = va_arg(ap, int);
- struct SrcList_item *pItem = &pSrc->a[k];
+ SrcList *pSrc;
+ int k;
+ struct SrcList_item *pItem;
+ if( (pAccum->printfFlags & SQLITE_PRINTF_INTERNAL)==0 ) return;
+ pSrc = va_arg(ap, SrcList*);
+ k = va_arg(ap, int);
+ pItem = &pSrc->a[k];
assert( bArgList==0 );
assert( k>=0 && knSrc );
if( pItem->zDatabase ){
@@ -25445,9 +26603,13 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
** the output.
*/
width -= length;
- if( width>0 && !flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' ');
- sqlite3StrAccumAppend(pAccum, bufpt, length);
- if( width>0 && flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' ');
+ if( width>0 ){
+ if( !flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' ');
+ sqlite3StrAccumAppend(pAccum, bufpt, length);
+ if( flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' ');
+ }else{
+ sqlite3StrAccumAppend(pAccum, bufpt, length);
+ }
if( zExtra ){
sqlite3DbFree(pAccum->db, zExtra);
@@ -25478,7 +26640,6 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
}else{
char *zOld = isMalloced(p) ? p->zText : 0;
i64 szNew = p->nChar;
- assert( (p->zText==0 || p->zText==p->zBase)==!isMalloced(p) );
szNew += N + 1;
if( szNew+p->nChar<=p->mxAlloc ){
/* Force exponential buffer size growth as long as it does not overflow,
@@ -25520,7 +26681,6 @@ SQLITE_PRIVATE void sqlite3AppendChar(StrAccum *p, int N, char c){
if( p->nChar+(i64)N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ){
return;
}
- assert( (p->zText==p->zBase)==!isMalloced(p) );
while( (N--)>0 ) p->zText[p->nChar++] = c;
}
@@ -25538,7 +26698,6 @@ static void SQLITE_NOINLINE enlargeAndAppend(StrAccum *p, const char *z, int N){
memcpy(&p->zText[p->nChar], z, N);
p->nChar += N;
}
- assert( (p->zText==0 || p->zText==p->zBase)==!isMalloced(p) );
}
/*
@@ -25552,7 +26711,7 @@ SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
assert( p->accError==0 || p->nAlloc==0 );
if( p->nChar+N >= p->nAlloc ){
enlargeAndAppend(p,z,N);
- }else{
+ }else if( N ){
assert( p->zText );
p->nChar += N;
memcpy(&p->zText[p->nChar-N], z, N);
@@ -25572,18 +26731,24 @@ SQLITE_PRIVATE void sqlite3StrAccumAppendAll(StrAccum *p, const char *z){
** Return a pointer to the resulting string. Return a NULL
** pointer if any kind of error was encountered.
*/
+static SQLITE_NOINLINE char *strAccumFinishRealloc(StrAccum *p){
+ char *zText;
+ assert( p->mxAlloc>0 && !isMalloced(p) );
+ zText = sqlite3DbMallocRaw(p->db, p->nChar+1 );
+ if( zText ){
+ memcpy(zText, p->zText, p->nChar+1);
+ p->printfFlags |= SQLITE_PRINTF_MALLOCED;
+ }else{
+ setStrAccumError(p, STRACCUM_NOMEM);
+ }
+ p->zText = zText;
+ return zText;
+}
SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum *p){
if( p->zText ){
- assert( (p->zText==p->zBase)==!isMalloced(p) );
p->zText[p->nChar] = 0;
if( p->mxAlloc>0 && !isMalloced(p) ){
- p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 );
- if( p->zText ){
- memcpy(p->zText, p->zBase, p->nChar+1);
- p->printfFlags |= SQLITE_PRINTF_MALLOCED;
- }else{
- setStrAccumError(p, STRACCUM_NOMEM);
- }
+ return strAccumFinishRealloc(p);
}
}
return p->zText;
@@ -25593,7 +26758,6 @@ SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum *p){
** Reset an StrAccum string. Reclaim all malloced memory.
*/
SQLITE_PRIVATE void sqlite3StrAccumReset(StrAccum *p){
- assert( (p->zText==0 || p->zText==p->zBase)==!isMalloced(p) );
if( isMalloced(p) ){
sqlite3DbFree(p->db, p->zText);
p->printfFlags &= ~SQLITE_PRINTF_MALLOCED;
@@ -25616,11 +26780,11 @@ SQLITE_PRIVATE void sqlite3StrAccumReset(StrAccum *p){
** allocations will ever occur.
*/
SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum *p, sqlite3 *db, char *zBase, int n, int mx){
- p->zText = p->zBase = zBase;
+ p->zText = zBase;
p->db = db;
- p->nChar = 0;
p->nAlloc = n;
p->mxAlloc = mx;
+ p->nChar = 0;
p->accError = 0;
p->printfFlags = 0;
}
@@ -25723,7 +26887,8 @@ SQLITE_API char *sqlite3_vsnprintf(int n, char *zBuf, const char *zFormat, va_li
#endif
sqlite3StrAccumInit(&acc, 0, zBuf, n, 0);
sqlite3VXPrintf(&acc, zFormat, ap);
- return sqlite3StrAccumFinish(&acc);
+ zBuf[acc.nChar] = 0;
+ return zBuf;
}
SQLITE_API char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){
char *z;
@@ -25785,8 +26950,15 @@ SQLITE_PRIVATE void sqlite3DebugPrintf(const char *zFormat, ...){
sqlite3VXPrintf(&acc, zFormat, ap);
va_end(ap);
sqlite3StrAccumFinish(&acc);
+#ifdef SQLITE_OS_TRACE_PROC
+ {
+ extern void SQLITE_OS_TRACE_PROC(const char *zBuf, int nBuf);
+ SQLITE_OS_TRACE_PROC(zBuf, sizeof(zBuf));
+ }
+#else
fprintf(stdout,"%s", zBuf);
fflush(stdout);
+#endif
}
#endif
@@ -25871,6 +27043,7 @@ static void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){
va_start(ap, zFormat);
sqlite3VXPrintf(&acc, zFormat, ap);
va_end(ap);
+ assert( acc.nChar>0 );
if( zBuf[acc.nChar-1]!='\n' ) sqlite3StrAccumAppend(&acc, "\n", 1);
sqlite3StrAccumFinish(&acc);
fprintf(stdout,"%s", zBuf);
@@ -25931,6 +27104,10 @@ SQLITE_PRIVATE void sqlite3TreeViewWith(TreeView *pView, const With *pWith, u8 m
SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
int n = 0;
int cnt = 0;
+ if( p==0 ){
+ sqlite3TreeViewLine(pView, "nil-SELECT");
+ return;
+ }
pView = sqlite3TreeViewPush(pView, moreToFollow);
if( p->pWith ){
sqlite3TreeViewWith(pView, p->pWith, 1);
@@ -25954,7 +27131,6 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m
if( p->pHaving ) n++;
if( p->pOrderBy ) n++;
if( p->pLimit ) n++;
- if( p->pOffset ) n++;
}
sqlite3TreeViewExprList(pView, p->pEList, (n--)>0, "result-set");
if( p->pSrc && p->pSrc->nSrc ){
@@ -26011,12 +27187,12 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m
}
if( p->pLimit ){
sqlite3TreeViewItem(pView, "LIMIT", (n--)>0);
- sqlite3TreeViewExpr(pView, p->pLimit, 0);
- sqlite3TreeViewPop(pView);
- }
- if( p->pOffset ){
- sqlite3TreeViewItem(pView, "OFFSET", (n--)>0);
- sqlite3TreeViewExpr(pView, p->pOffset, 0);
+ sqlite3TreeViewExpr(pView, p->pLimit->pLeft, p->pLimit->pRight!=0);
+ if( p->pLimit->pRight ){
+ sqlite3TreeViewItem(pView, "OFFSET", (n--)>0);
+ sqlite3TreeViewExpr(pView, p->pLimit->pRight, 0);
+ sqlite3TreeViewPop(pView);
+ }
sqlite3TreeViewPop(pView);
}
if( p->pPrior ){
@@ -26039,7 +27215,7 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m
SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
const char *zBinOp = 0; /* Binary operator */
const char *zUniOp = 0; /* Unary operator */
- char zFlgs[30];
+ char zFlgs[60];
pView = sqlite3TreeViewPush(pView, moreToFollow);
if( pExpr==0 ){
sqlite3TreeViewLine(pView, "nil");
@@ -26047,7 +27223,12 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
return;
}
if( pExpr->flags ){
- sqlite3_snprintf(sizeof(zFlgs),zFlgs," flags=0x%x",pExpr->flags);
+ if( ExprHasProperty(pExpr, EP_FromJoin) ){
+ sqlite3_snprintf(sizeof(zFlgs),zFlgs," flags=0x%x iRJT=%d",
+ pExpr->flags, pExpr->iRightJoinTable);
+ }else{
+ sqlite3_snprintf(sizeof(zFlgs),zFlgs," flags=0x%x",pExpr->flags);
+ }
}else{
zFlgs[0] = 0;
}
@@ -26178,17 +27359,17 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
}
#ifndef SQLITE_OMIT_SUBQUERY
case TK_EXISTS: {
- sqlite3TreeViewLine(pView, "EXISTS-expr");
+ sqlite3TreeViewLine(pView, "EXISTS-expr flags=0x%x", pExpr->flags);
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
break;
}
case TK_SELECT: {
- sqlite3TreeViewLine(pView, "SELECT-expr");
+ sqlite3TreeViewLine(pView, "SELECT-expr flags=0x%x", pExpr->flags);
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
break;
}
case TK_IN: {
- sqlite3TreeViewLine(pView, "IN");
+ sqlite3TreeViewLine(pView, "IN flags=0x%x", pExpr->flags);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
@@ -26266,6 +27447,11 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
sqlite3TreeViewSelect(pView, pExpr->pLeft->x.pSelect, 0);
break;
}
+ case TK_IF_NULL_ROW: {
+ sqlite3TreeViewLine(pView, "IF-NULL-ROW %d", pExpr->iTable);
+ sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
+ break;
+ }
default: {
sqlite3TreeViewLine(pView, "op=%d", pExpr->op);
break;
@@ -26299,12 +27485,20 @@ SQLITE_PRIVATE void sqlite3TreeViewBareExprList(
sqlite3TreeViewLine(pView, "%s", zLabel);
for(i=0; inExpr; i++){
int j = pList->a[i].u.x.iOrderByCol;
- if( j ){
+ char *zName = pList->a[i].zName;
+ if( j || zName ){
sqlite3TreeViewPush(pView, 0);
+ }
+ if( zName ){
+ sqlite3TreeViewLine(pView, "AS %s", zName);
+ }
+ if( j ){
sqlite3TreeViewLine(pView, "iOrderByCol=%d", j);
}
sqlite3TreeViewExpr(pView, pList->a[i].pExpr, inExpr-1);
- if( j ) sqlite3TreeViewPop(pView);
+ if( j || zName ){
+ sqlite3TreeViewPop(pView);
+ }
}
}
}
@@ -26431,7 +27625,7 @@ SQLITE_API void sqlite3_randomness(int N, void *pBuf){
sqlite3_mutex_leave(mutex);
}
-#ifndef SQLITE_OMIT_BUILTIN_TEST
+#ifndef SQLITE_UNTESTABLE
/*
** For testing purposes, we sometimes want to preserve the state of
** PRNG and restore the PRNG to its saved state at a later time, or
@@ -26456,7 +27650,7 @@ SQLITE_PRIVATE void sqlite3PrngRestoreState(void){
sizeof(sqlite3Prng)
);
}
-#endif /* SQLITE_OMIT_BUILTIN_TEST */
+#endif /* SQLITE_UNTESTABLE */
/************** End of random.c **********************************************/
/************** Begin file threads.c *****************************************/
@@ -27071,7 +28265,9 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desired
#endif
return SQLITE_OK;
}
+#endif /* SQLITE_OMIT_UTF16 */
+#ifndef SQLITE_OMIT_UTF16
/*
** This routine checks for a byte-order mark at the beginning of the
** UTF-16 string stored in *pMem. If one is present, it is removed and
@@ -27314,7 +28510,7 @@ SQLITE_PRIVATE void sqlite3Coverage(int x){
** Return whatever integer value the test callback returns, or return
** SQLITE_OK if no test callback is installed.
*/
-#ifndef SQLITE_OMIT_BUILTIN_TEST
+#ifndef SQLITE_UNTESTABLE
SQLITE_PRIVATE int sqlite3FaultSim(int iTest){
int (*xCallback)(int) = sqlite3GlobalConfig.xTestCallback;
return xCallback ? xCallback(iTest) : SQLITE_OK;
@@ -27592,6 +28788,45 @@ SQLITE_API int sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){
return N<0 ? 0 : UpperToLower[*a] - UpperToLower[*b];
}
+/*
+** Compute 10 to the E-th power. Examples: E==1 results in 10.
+** E==2 results in 100. E==50 results in 1.0e50.
+**
+** This routine only works for values of E between 1 and 341.
+*/
+static LONGDOUBLE_TYPE sqlite3Pow10(int E){
+#if defined(_MSC_VER)
+ static const LONGDOUBLE_TYPE x[] = {
+ 1.0e+001,
+ 1.0e+002,
+ 1.0e+004,
+ 1.0e+008,
+ 1.0e+016,
+ 1.0e+032,
+ 1.0e+064,
+ 1.0e+128,
+ 1.0e+256
+ };
+ LONGDOUBLE_TYPE r = 1.0;
+ int i;
+ assert( E>=0 && E<=307 );
+ for(i=0; E!=0; i++, E >>=1){
+ if( E & 1 ) r *= x[i];
+ }
+ return r;
+#else
+ LONGDOUBLE_TYPE x = 10.0;
+ LONGDOUBLE_TYPE r = 1.0;
+ while(1){
+ if( E & 1 ) r *= x;
+ E >>= 1;
+ if( E==0 ) break;
+ x *= x;
+ }
+ return r;
+#endif
+}
+
/*
** The string z[] is an text representation of a real number.
** Convert this string to a double and write it into *pResult.
@@ -27659,12 +28894,12 @@ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 en
/* copy max significant digits to significand */
while( z=zEnd ) goto do_atof_calc;
/* if decimal point is present */
@@ -27677,7 +28912,7 @@ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 en
s = s*10 + (*z - '0');
d--;
}
- z+=incr, nDigits++;
+ z+=incr; nDigits++;
}
}
if( z>=zEnd ) goto do_atof_calc;
@@ -27747,11 +28982,10 @@ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 en
if( e==0 ){ /*OPTIMIZATION-IF-TRUE*/
result = (double)s;
}else{
- LONGDOUBLE_TYPE scale = 1.0;
/* attempt to handle extremely small/large numbers better */
if( e>307 ){ /*OPTIMIZATION-IF-TRUE*/
if( e<342 ){ /*OPTIMIZATION-IF-TRUE*/
- while( e%308 ) { scale *= 1.0e+1; e -= 1; }
+ LONGDOUBLE_TYPE scale = sqlite3Pow10(e-308);
if( esign<0 ){
result = s / scale;
result /= 1.0e+308;
@@ -27763,14 +28997,15 @@ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 en
if( esign<0 ){
result = 0.0*s;
}else{
+#ifdef INFINITY
+ result = INFINITY*s;
+#else
result = 1e308*1e308*s; /* Infinity */
+#endif
}
}
}else{
- /* 1.0e+22 is the largest power of 10 than can be
- ** represented exactly. */
- while( e%22 ) { scale *= 1.0e+1; e -= 1; }
- while( e>0 ) { scale *= 1.0e+22; e -= 22; }
+ LONGDOUBLE_TYPE scale = sqlite3Pow10(e);
if( esign<0 ){
result = s / scale;
}else{
@@ -27825,16 +29060,12 @@ static int compare2pow63(const char *zNum, int incr){
** Convert zNum to a 64-bit signed integer. zNum must be decimal. This
** routine does *not* accept hexadecimal notation.
**
-** If the zNum value is representable as a 64-bit twos-complement
-** integer, then write that value into *pNum and return 0.
-**
-** If zNum is exactly 9223372036854775808, return 2. This special
-** case is broken out because while 9223372036854775808 cannot be a
-** signed 64-bit integer, its negative -9223372036854775808 can be.
+** Returns:
**
-** If zNum is too big for a 64-bit integer and is not
-** 9223372036854775808 or if zNum contains any non-numeric text,
-** then return 1.
+** 0 Successful transformation. Fits in a 64-bit signed integer.
+** 1 Excess text after the integer value
+** 2 Integer too large for a 64-bit signed integer or is malformed
+** 3 Special case of 9223372036854775808
**
** length is the number of bytes in the string (bytes, not characters).
** The string is not necessarily zero-terminated. The encoding is
@@ -27847,6 +29078,7 @@ SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc
int i;
int c = 0;
int nonNum = 0; /* True if input contains UTF16 with high byte non-zero */
+ int rc; /* Baseline return code */
const char *zStart;
const char *zEnd = zNum + length;
assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
@@ -27886,31 +29118,35 @@ SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc
testcase( i==20 );
if( &zNum[i]19*incr /* Too many digits */
|| nonNum /* UTF16 with high-order bytes non-zero */
){
+ rc = 1;
+ }else{
+ rc = 0;
+ }
+ if( i>19*incr ){ /* Too many digits */
/* zNum is empty or contains non-numeric text or is longer
** than 19 digits (thus guaranteeing that it is too large) */
- return 1;
+ return 2;
}else if( i<19*incr ){
/* Less than 19 digits, so we know that it fits in 64 bits */
assert( u<=LARGEST_INT64 );
- return 0;
+ return rc;
}else{
/* zNum is a 19-digit numbers. Compare it against 9223372036854775808. */
c = compare2pow63(zNum, incr);
if( c<0 ){
/* zNum is less than 9223372036854775808 so it fits */
assert( u<=LARGEST_INT64 );
- return 0;
+ return rc;
}else if( c>0 ){
/* zNum is greater than 9223372036854775808 so it overflows */
- return 1;
+ return 2;
}else{
/* zNum is exactly 9223372036854775808. Fits if negative. The
** special case 2 overflow if positive */
assert( u-1==LARGEST_INT64 );
- return neg ? 0 : 2;
+ return neg ? rc : 3;
}
}
}
@@ -27923,8 +29159,9 @@ SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc
** Returns:
**
** 0 Successful transformation. Fits in a 64-bit signed integer.
-** 1 Integer too large for a 64-bit signed integer or is malformed
-** 2 Special case of 9223372036854775808
+** 1 Excess text after the integer value
+** 2 Integer too large for a 64-bit signed integer or is malformed
+** 3 Special case of 9223372036854775808
*/
SQLITE_PRIVATE int sqlite3DecOrHexToI64(const char *z, i64 *pOut){
#ifndef SQLITE_OMIT_HEX_INTEGER
@@ -27938,7 +29175,7 @@ SQLITE_PRIVATE int sqlite3DecOrHexToI64(const char *z, i64 *pOut){
u = u*16 + sqlite3HexToInt(z[k]);
}
memcpy(pOut, &u, 8);
- return (z[k]==0 && k-i<=16) ? 0 : 1;
+ return (z[k]==0 && k-i<=16) ? 0 : 2;
}else
#endif /* SQLITE_OMIT_HEX_INTEGER */
{
@@ -27985,6 +29222,7 @@ SQLITE_PRIVATE int sqlite3GetInt32(const char *zNum, int *pValue){
}
}
#endif
+ if( !sqlite3Isdigit(zNum[0]) ) return 0;
while( zNum[0]=='0' ) zNum++;
for(i=0; i<11 && (c = zNum[i] - '0')>=0 && c<=9; i++){
v = v*10 + c;
@@ -28412,13 +29650,11 @@ SQLITE_PRIVATE u32 sqlite3Get4byte(const u8 *p){
u32 x;
memcpy(&x,p,4);
return x;
-#elif SQLITE_BYTEORDER==1234 && !defined(SQLITE_DISABLE_INTRINSIC) \
- && defined(__GNUC__) && GCC_VERSION>=4003000
+#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000
u32 x;
memcpy(&x,p,4);
return __builtin_bswap32(x);
-#elif SQLITE_BYTEORDER==1234 && !defined(SQLITE_DISABLE_INTRINSIC) \
- && defined(_MSC_VER) && _MSC_VER>=1300
+#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
u32 x;
memcpy(&x,p,4);
return _byteswap_ulong(x);
@@ -28430,12 +29666,10 @@ SQLITE_PRIVATE u32 sqlite3Get4byte(const u8 *p){
SQLITE_PRIVATE void sqlite3Put4byte(unsigned char *p, u32 v){
#if SQLITE_BYTEORDER==4321
memcpy(p,&v,4);
-#elif SQLITE_BYTEORDER==1234 && !defined(SQLITE_DISABLE_INTRINSIC) \
- && defined(__GNUC__) && GCC_VERSION>=4003000
+#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000
u32 x = __builtin_bswap32(v);
memcpy(p,&x,4);
-#elif SQLITE_BYTEORDER==1234 && !defined(SQLITE_DISABLE_INTRINSIC) \
- && defined(_MSC_VER) && _MSC_VER>=1300
+#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
u32 x = _byteswap_ulong(v);
memcpy(p,&x,4);
#else
@@ -28551,6 +29785,9 @@ SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3 *db){
** overflow, leave *pA unchanged and return 1.
*/
SQLITE_PRIVATE int sqlite3AddInt64(i64 *pA, i64 iB){
+#if GCC_VERSION>=5004000 && !defined(__INTEL_COMPILER)
+ return __builtin_add_overflow(*pA, iB, pA);
+#else
i64 iA = *pA;
testcase( iA==0 ); testcase( iA==1 );
testcase( iB==-1 ); testcase( iB==0 );
@@ -28565,8 +29802,12 @@ SQLITE_PRIVATE int sqlite3AddInt64(i64 *pA, i64 iB){
}
*pA += iB;
return 0;
+#endif
}
SQLITE_PRIVATE int sqlite3SubInt64(i64 *pA, i64 iB){
+#if GCC_VERSION>=5004000 && !defined(__INTEL_COMPILER)
+ return __builtin_sub_overflow(*pA, iB, pA);
+#else
testcase( iB==SMALLEST_INT64+1 );
if( iB==SMALLEST_INT64 ){
testcase( (*pA)==(-1) ); testcase( (*pA)==0 );
@@ -28576,8 +29817,12 @@ SQLITE_PRIVATE int sqlite3SubInt64(i64 *pA, i64 iB){
}else{
return sqlite3AddInt64(pA, -iB);
}
+#endif
}
SQLITE_PRIVATE int sqlite3MulInt64(i64 *pA, i64 iB){
+#if GCC_VERSION>=5004000 && !defined(__INTEL_COMPILER)
+ return __builtin_mul_overflow(*pA, iB, pA);
+#else
i64 iA = *pA;
if( iB>0 ){
if( iA>LARGEST_INT64/iB ) return 1;
@@ -28593,6 +29838,7 @@ SQLITE_PRIVATE int sqlite3MulInt64(i64 *pA, i64 iB){
}
*pA = iA*iB;
return 0;
+#endif
}
/*
@@ -28676,8 +29922,14 @@ SQLITE_PRIVATE LogEst sqlite3LogEst(u64 x){
if( x<2 ) return 0;
while( x<8 ){ y -= 10; x <<= 1; }
}else{
+#if GCC_VERSION>=5004000
+ int i = 60 - __builtin_clzll(x);
+ y += i*10;
+ x >>= i;
+#else
while( x>255 ){ y += 40; x >>= 4; } /*OPTIMIZATION-IF-TRUE*/
while( x>15 ){ y += 10; x >>= 1; }
+#endif
}
return a[x&7] + y - 10;
}
@@ -28726,6 +29978,109 @@ SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst x){
}
#endif /* defined SCANSTAT or STAT4 or ESTIMATED_ROWS */
+/*
+** Add a new name/number pair to a VList. This might require that the
+** VList object be reallocated, so return the new VList. If an OOM
+** error occurs, the original VList returned and the
+** db->mallocFailed flag is set.
+**
+** A VList is really just an array of integers. To destroy a VList,
+** simply pass it to sqlite3DbFree().
+**
+** The first integer is the number of integers allocated for the whole
+** VList. The second integer is the number of integers actually used.
+** Each name/number pair is encoded by subsequent groups of 3 or more
+** integers.
+**
+** Each name/number pair starts with two integers which are the numeric
+** value for the pair and the size of the name/number pair, respectively.
+** The text name overlays one or more following integers. The text name
+** is always zero-terminated.
+**
+** Conceptually:
+**
+** struct VList {
+** int nAlloc; // Number of allocated slots
+** int nUsed; // Number of used slots
+** struct VListEntry {
+** int iValue; // Value for this entry
+** int nSlot; // Slots used by this entry
+** // ... variable name goes here
+** } a[0];
+** }
+**
+** During code generation, pointers to the variable names within the
+** VList are taken. When that happens, nAlloc is set to zero as an
+** indication that the VList may never again be enlarged, since the
+** accompanying realloc() would invalidate the pointers.
+*/
+SQLITE_PRIVATE VList *sqlite3VListAdd(
+ sqlite3 *db, /* The database connection used for malloc() */
+ VList *pIn, /* The input VList. Might be NULL */
+ const char *zName, /* Name of symbol to add */
+ int nName, /* Bytes of text in zName */
+ int iVal /* Value to associate with zName */
+){
+ int nInt; /* number of sizeof(int) objects needed for zName */
+ char *z; /* Pointer to where zName will be stored */
+ int i; /* Index in pIn[] where zName is stored */
+
+ nInt = nName/4 + 3;
+ assert( pIn==0 || pIn[0]>=3 ); /* Verify ok to add new elements */
+ if( pIn==0 || pIn[1]+nInt > pIn[0] ){
+ /* Enlarge the allocation */
+ int nAlloc = (pIn ? pIn[0]*2 : 10) + nInt;
+ VList *pOut = sqlite3DbRealloc(db, pIn, nAlloc*sizeof(int));
+ if( pOut==0 ) return pIn;
+ if( pIn==0 ) pOut[1] = 2;
+ pIn = pOut;
+ pIn[0] = nAlloc;
+ }
+ i = pIn[1];
+ pIn[i] = iVal;
+ pIn[i+1] = nInt;
+ z = (char*)&pIn[i+2];
+ pIn[1] = i+nInt;
+ assert( pIn[1]<=pIn[0] );
+ memcpy(z, zName, nName);
+ z[nName] = 0;
+ return pIn;
+}
+
+/*
+** Return a pointer to the name of a variable in the given VList that
+** has the value iVal. Or return a NULL if there is no such variable in
+** the list
+*/
+SQLITE_PRIVATE const char *sqlite3VListNumToName(VList *pIn, int iVal){
+ int i, mx;
+ if( pIn==0 ) return 0;
+ mx = pIn[1];
+ i = 2;
+ do{
+ if( pIn[i]==iVal ) return (char*)&pIn[i+2];
+ i += pIn[i+1];
+ }while( iht ){ /*OPTIMIZATION-IF-TRUE*/
struct _ht *pEntry;
@@ -28893,7 +30250,7 @@ static HashElem *findElementWithHash(
elem = pH->first;
count = pH->count;
}
- *pHash = h;
+ if( pHash ) *pHash = h;
while( count-- ){
assert( elem!=0 );
if( sqlite3StrICmp(elem->pKey,pKey)==0 ){
@@ -28901,7 +30258,7 @@ static HashElem *findElementWithHash(
}
elem = elem->next;
}
- return 0;
+ return &nullElement;
}
/* Remove a single entry from the hash table given a pointer to that
@@ -28943,13 +30300,9 @@ static void removeElementGivenHash(
** found, or NULL if there is no match.
*/
SQLITE_PRIVATE void *sqlite3HashFind(const Hash *pH, const char *pKey){
- HashElem *elem; /* The element that matches key */
- unsigned int h; /* A hash on key */
-
assert( pH!=0 );
assert( pKey!=0 );
- elem = findElementWithHash(pH, pKey, &h);
- return elem ? elem->data : 0;
+ return findElementWithHash(pH, pKey, 0)->data;
}
/* Insert an element into the hash table pH. The key is pKey
@@ -28974,7 +30327,7 @@ SQLITE_PRIVATE void *sqlite3HashInsert(Hash *pH, const char *pKey, void *data){
assert( pH!=0 );
assert( pKey!=0 );
elem = findElementWithHash(pH,pKey,&h);
- if( elem ){
+ if( elem->data ){
void *old_data = elem->data;
if( data==0 ){
removeElementGivenHash(pH,elem,h);
@@ -29037,146 +30390,153 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 20 */ "Once" OpHelp(""),
/* 21 */ "If" OpHelp(""),
/* 22 */ "IfNot" OpHelp(""),
- /* 23 */ "SeekLT" OpHelp("key=r[P3@P4]"),
- /* 24 */ "SeekLE" OpHelp("key=r[P3@P4]"),
- /* 25 */ "SeekGE" OpHelp("key=r[P3@P4]"),
- /* 26 */ "SeekGT" OpHelp("key=r[P3@P4]"),
- /* 27 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"),
- /* 28 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"),
- /* 29 */ "NoConflict" OpHelp("key=r[P3@P4]"),
- /* 30 */ "NotFound" OpHelp("key=r[P3@P4]"),
- /* 31 */ "Found" OpHelp("key=r[P3@P4]"),
- /* 32 */ "SeekRowid" OpHelp("intkey=r[P3]"),
- /* 33 */ "NotExists" OpHelp("intkey=r[P3]"),
- /* 34 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"),
- /* 35 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"),
- /* 36 */ "Ne" OpHelp("IF r[P3]!=r[P1]"),
- /* 37 */ "Eq" OpHelp("IF r[P3]==r[P1]"),
- /* 38 */ "Gt" OpHelp("IF r[P3]>r[P1]"),
- /* 39 */ "Le" OpHelp("IF r[P3]<=r[P1]"),
- /* 40 */ "Lt" OpHelp("IF r[P3]=r[P1]"),
- /* 42 */ "ElseNotEq" OpHelp(""),
- /* 43 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"),
- /* 44 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"),
- /* 45 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<>r[P1]"),
- /* 47 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"),
- /* 48 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"),
- /* 49 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"),
- /* 50 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"),
- /* 51 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"),
- /* 52 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"),
- /* 53 */ "Last" OpHelp(""),
- /* 54 */ "BitNot" OpHelp("r[P1]= ~r[P1]"),
- /* 55 */ "SorterSort" OpHelp(""),
- /* 56 */ "Sort" OpHelp(""),
- /* 57 */ "Rewind" OpHelp(""),
- /* 58 */ "IdxLE" OpHelp("key=r[P3@P4]"),
- /* 59 */ "IdxGT" OpHelp("key=r[P3@P4]"),
- /* 60 */ "IdxLT" OpHelp("key=r[P3@P4]"),
- /* 61 */ "IdxGE" OpHelp("key=r[P3@P4]"),
- /* 62 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"),
- /* 63 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"),
- /* 64 */ "Program" OpHelp(""),
- /* 65 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"),
- /* 66 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"),
- /* 67 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]-=P3, goto P2"),
- /* 68 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"),
- /* 69 */ "IncrVacuum" OpHelp(""),
- /* 70 */ "VNext" OpHelp(""),
- /* 71 */ "Init" OpHelp("Start at P2"),
- /* 72 */ "Return" OpHelp(""),
- /* 73 */ "EndCoroutine" OpHelp(""),
- /* 74 */ "HaltIfNull" OpHelp("if r[P3]=null halt"),
- /* 75 */ "Halt" OpHelp(""),
- /* 76 */ "Integer" OpHelp("r[P2]=P1"),
- /* 77 */ "Int64" OpHelp("r[P2]=P4"),
- /* 78 */ "String" OpHelp("r[P2]='P4' (len=P1)"),
- /* 79 */ "Null" OpHelp("r[P2..P3]=NULL"),
- /* 80 */ "SoftNull" OpHelp("r[P1]=NULL"),
- /* 81 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"),
- /* 82 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"),
- /* 83 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"),
- /* 84 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"),
- /* 85 */ "SCopy" OpHelp("r[P2]=r[P1]"),
- /* 86 */ "IntCopy" OpHelp("r[P2]=r[P1]"),
- /* 87 */ "ResultRow" OpHelp("output=r[P1@P2]"),
- /* 88 */ "CollSeq" OpHelp(""),
- /* 89 */ "Function0" OpHelp("r[P3]=func(r[P2@P5])"),
- /* 90 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"),
- /* 91 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"),
- /* 92 */ "RealAffinity" OpHelp(""),
- /* 93 */ "Cast" OpHelp("affinity(r[P1])"),
- /* 94 */ "Permutation" OpHelp(""),
- /* 95 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"),
- /* 96 */ "Column" OpHelp("r[P3]=PX"),
+ /* 23 */ "IfNullRow" OpHelp("if P1.nullRow then r[P3]=NULL, goto P2"),
+ /* 24 */ "SeekLT" OpHelp("key=r[P3@P4]"),
+ /* 25 */ "SeekLE" OpHelp("key=r[P3@P4]"),
+ /* 26 */ "SeekGE" OpHelp("key=r[P3@P4]"),
+ /* 27 */ "SeekGT" OpHelp("key=r[P3@P4]"),
+ /* 28 */ "NoConflict" OpHelp("key=r[P3@P4]"),
+ /* 29 */ "NotFound" OpHelp("key=r[P3@P4]"),
+ /* 30 */ "Found" OpHelp("key=r[P3@P4]"),
+ /* 31 */ "SeekRowid" OpHelp("intkey=r[P3]"),
+ /* 32 */ "NotExists" OpHelp("intkey=r[P3]"),
+ /* 33 */ "Last" OpHelp(""),
+ /* 34 */ "IfSmaller" OpHelp(""),
+ /* 35 */ "SorterSort" OpHelp(""),
+ /* 36 */ "Sort" OpHelp(""),
+ /* 37 */ "Rewind" OpHelp(""),
+ /* 38 */ "IdxLE" OpHelp("key=r[P3@P4]"),
+ /* 39 */ "IdxGT" OpHelp("key=r[P3@P4]"),
+ /* 40 */ "IdxLT" OpHelp("key=r[P3@P4]"),
+ /* 41 */ "IdxGE" OpHelp("key=r[P3@P4]"),
+ /* 42 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"),
+ /* 43 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"),
+ /* 44 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"),
+ /* 45 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"),
+ /* 46 */ "Program" OpHelp(""),
+ /* 47 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"),
+ /* 48 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"),
+ /* 49 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"),
+ /* 50 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"),
+ /* 51 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"),
+ /* 52 */ "Ne" OpHelp("IF r[P3]!=r[P1]"),
+ /* 53 */ "Eq" OpHelp("IF r[P3]==r[P1]"),
+ /* 54 */ "Gt" OpHelp("IF r[P3]>r[P1]"),
+ /* 55 */ "Le" OpHelp("IF r[P3]<=r[P1]"),
+ /* 56 */ "Lt" OpHelp("IF r[P3]=r[P1]"),
+ /* 58 */ "ElseNotEq" OpHelp(""),
+ /* 59 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"),
+ /* 60 */ "IncrVacuum" OpHelp(""),
+ /* 61 */ "VNext" OpHelp(""),
+ /* 62 */ "Init" OpHelp("Start at P2"),
+ /* 63 */ "Return" OpHelp(""),
+ /* 64 */ "EndCoroutine" OpHelp(""),
+ /* 65 */ "HaltIfNull" OpHelp("if r[P3]=null halt"),
+ /* 66 */ "Halt" OpHelp(""),
+ /* 67 */ "Integer" OpHelp("r[P2]=P1"),
+ /* 68 */ "Int64" OpHelp("r[P2]=P4"),
+ /* 69 */ "String" OpHelp("r[P2]='P4' (len=P1)"),
+ /* 70 */ "Null" OpHelp("r[P2..P3]=NULL"),
+ /* 71 */ "SoftNull" OpHelp("r[P1]=NULL"),
+ /* 72 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"),
+ /* 73 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"),
+ /* 74 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"),
+ /* 75 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"),
+ /* 76 */ "SCopy" OpHelp("r[P2]=r[P1]"),
+ /* 77 */ "IntCopy" OpHelp("r[P2]=r[P1]"),
+ /* 78 */ "ResultRow" OpHelp("output=r[P1@P2]"),
+ /* 79 */ "CollSeq" OpHelp(""),
+ /* 80 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"),
+ /* 81 */ "RealAffinity" OpHelp(""),
+ /* 82 */ "Cast" OpHelp("affinity(r[P1])"),
+ /* 83 */ "Permutation" OpHelp(""),
+ /* 84 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"),
+ /* 85 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"),
+ /* 86 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<>r[P1]"),
+ /* 88 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"),
+ /* 89 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"),
+ /* 90 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"),
+ /* 91 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"),
+ /* 92 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"),
+ /* 93 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"),
+ /* 94 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"),
+ /* 95 */ "BitNot" OpHelp("r[P1]= ~r[P1]"),
+ /* 96 */ "Offset" OpHelp("r[P3] = sqlite_offset(P1)"),
/* 97 */ "String8" OpHelp("r[P2]='P4'"),
- /* 98 */ "Affinity" OpHelp("affinity(r[P1@P2])"),
- /* 99 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"),
- /* 100 */ "Count" OpHelp("r[P2]=count()"),
- /* 101 */ "ReadCookie" OpHelp(""),
- /* 102 */ "SetCookie" OpHelp(""),
- /* 103 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"),
- /* 104 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
- /* 105 */ "OpenWrite" OpHelp("root=P2 iDb=P3"),
- /* 106 */ "OpenAutoindex" OpHelp("nColumn=P2"),
- /* 107 */ "OpenEphemeral" OpHelp("nColumn=P2"),
- /* 108 */ "SorterOpen" OpHelp(""),
- /* 109 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"),
- /* 110 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"),
- /* 111 */ "Close" OpHelp(""),
- /* 112 */ "ColumnsUsed" OpHelp(""),
- /* 113 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"),
- /* 114 */ "NewRowid" OpHelp("r[P2]=rowid"),
- /* 115 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
- /* 116 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"),
- /* 117 */ "Delete" OpHelp(""),
- /* 118 */ "ResetCount" OpHelp(""),
- /* 119 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
- /* 120 */ "SorterData" OpHelp("r[P2]=data"),
- /* 121 */ "RowKey" OpHelp("r[P2]=key"),
- /* 122 */ "RowData" OpHelp("r[P2]=data"),
- /* 123 */ "Rowid" OpHelp("r[P2]=rowid"),
- /* 124 */ "NullRow" OpHelp(""),
- /* 125 */ "SorterInsert" OpHelp(""),
- /* 126 */ "IdxInsert" OpHelp("key=r[P2]"),
- /* 127 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
- /* 128 */ "Seek" OpHelp("Move P3 to P1.rowid"),
- /* 129 */ "IdxRowid" OpHelp("r[P2]=rowid"),
- /* 130 */ "Destroy" OpHelp(""),
- /* 131 */ "Clear" OpHelp(""),
+ /* 98 */ "Column" OpHelp("r[P3]=PX"),
+ /* 99 */ "Affinity" OpHelp("affinity(r[P1@P2])"),
+ /* 100 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"),
+ /* 101 */ "Count" OpHelp("r[P2]=count()"),
+ /* 102 */ "ReadCookie" OpHelp(""),
+ /* 103 */ "SetCookie" OpHelp(""),
+ /* 104 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"),
+ /* 105 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
+ /* 106 */ "OpenWrite" OpHelp("root=P2 iDb=P3"),
+ /* 107 */ "OpenDup" OpHelp(""),
+ /* 108 */ "OpenAutoindex" OpHelp("nColumn=P2"),
+ /* 109 */ "OpenEphemeral" OpHelp("nColumn=P2"),
+ /* 110 */ "SorterOpen" OpHelp(""),
+ /* 111 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"),
+ /* 112 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"),
+ /* 113 */ "Close" OpHelp(""),
+ /* 114 */ "ColumnsUsed" OpHelp(""),
+ /* 115 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"),
+ /* 116 */ "NewRowid" OpHelp("r[P2]=rowid"),
+ /* 117 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
+ /* 118 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"),
+ /* 119 */ "Delete" OpHelp(""),
+ /* 120 */ "ResetCount" OpHelp(""),
+ /* 121 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
+ /* 122 */ "SorterData" OpHelp("r[P2]=data"),
+ /* 123 */ "RowData" OpHelp("r[P2]=data"),
+ /* 124 */ "Rowid" OpHelp("r[P2]=rowid"),
+ /* 125 */ "NullRow" OpHelp(""),
+ /* 126 */ "SeekEnd" OpHelp(""),
+ /* 127 */ "SorterInsert" OpHelp("key=r[P2]"),
+ /* 128 */ "IdxInsert" OpHelp("key=r[P2]"),
+ /* 129 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
+ /* 130 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"),
+ /* 131 */ "IdxRowid" OpHelp("r[P2]=rowid"),
/* 132 */ "Real" OpHelp("r[P2]=P4"),
- /* 133 */ "ResetSorter" OpHelp(""),
- /* 134 */ "CreateIndex" OpHelp("r[P2]=root iDb=P1"),
- /* 135 */ "CreateTable" OpHelp("r[P2]=root iDb=P1"),
- /* 136 */ "ParseSchema" OpHelp(""),
- /* 137 */ "LoadAnalysis" OpHelp(""),
- /* 138 */ "DropTable" OpHelp(""),
- /* 139 */ "DropIndex" OpHelp(""),
- /* 140 */ "DropTrigger" OpHelp(""),
- /* 141 */ "IntegrityCk" OpHelp(""),
- /* 142 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
- /* 143 */ "Param" OpHelp(""),
- /* 144 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
- /* 145 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
- /* 146 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"),
- /* 147 */ "AggStep0" OpHelp("accum=r[P3] step(r[P2@P5])"),
- /* 148 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"),
- /* 149 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
- /* 150 */ "Expire" OpHelp(""),
- /* 151 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
- /* 152 */ "VBegin" OpHelp(""),
- /* 153 */ "VCreate" OpHelp(""),
- /* 154 */ "VDestroy" OpHelp(""),
- /* 155 */ "VOpen" OpHelp(""),
- /* 156 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
- /* 157 */ "VRename" OpHelp(""),
- /* 158 */ "Pagecount" OpHelp(""),
- /* 159 */ "MaxPgcnt" OpHelp(""),
- /* 160 */ "CursorHint" OpHelp(""),
- /* 161 */ "Noop" OpHelp(""),
- /* 162 */ "Explain" OpHelp(""),
+ /* 133 */ "Destroy" OpHelp(""),
+ /* 134 */ "Clear" OpHelp(""),
+ /* 135 */ "ResetSorter" OpHelp(""),
+ /* 136 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"),
+ /* 137 */ "SqlExec" OpHelp(""),
+ /* 138 */ "ParseSchema" OpHelp(""),
+ /* 139 */ "LoadAnalysis" OpHelp(""),
+ /* 140 */ "DropTable" OpHelp(""),
+ /* 141 */ "DropIndex" OpHelp(""),
+ /* 142 */ "DropTrigger" OpHelp(""),
+ /* 143 */ "IntegrityCk" OpHelp(""),
+ /* 144 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
+ /* 145 */ "Param" OpHelp(""),
+ /* 146 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
+ /* 147 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
+ /* 148 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"),
+ /* 149 */ "AggStep0" OpHelp("accum=r[P3] step(r[P2@P5])"),
+ /* 150 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"),
+ /* 151 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
+ /* 152 */ "Expire" OpHelp(""),
+ /* 153 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
+ /* 154 */ "VBegin" OpHelp(""),
+ /* 155 */ "VCreate" OpHelp(""),
+ /* 156 */ "VDestroy" OpHelp(""),
+ /* 157 */ "VOpen" OpHelp(""),
+ /* 158 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
+ /* 159 */ "VRename" OpHelp(""),
+ /* 160 */ "Pagecount" OpHelp(""),
+ /* 161 */ "MaxPgcnt" OpHelp(""),
+ /* 162 */ "PureFunc0" OpHelp(""),
+ /* 163 */ "Function0" OpHelp("r[P3]=func(r[P2@P5])"),
+ /* 164 */ "PureFunc" OpHelp(""),
+ /* 165 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"),
+ /* 166 */ "Trace" OpHelp(""),
+ /* 167 */ "CursorHint" OpHelp(""),
+ /* 168 */ "Noop" OpHelp(""),
+ /* 169 */ "Explain" OpHelp(""),
};
return azName[i];
}
@@ -29276,6 +30636,7 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
#include
#include
#include
+#include
#include
/* #include */
#include
@@ -29285,7 +30646,7 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
#endif
#if SQLITE_ENABLE_LOCKING_STYLE
-# include
+/* # include */
# include
# include
#endif /* SQLITE_ENABLE_LOCKING_STYLE */
@@ -29395,7 +30756,7 @@ struct unixFile {
unsigned short int ctrlFlags; /* Behavioral bits. UNIXFILE_* flags */
int lastErrno; /* The unix errno from last I/O error */
void *lockingContext; /* Locking style specific state */
- UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */
+ UnixUnusedFd *pPreallocatedUnused; /* Pre-allocated UnixUnusedFd */
const char *zPath; /* Name of the file */
unixShm *pShm; /* Shared memory segment information */
int szChunk; /* Configured by FCNTL_CHUNK_SIZE */
@@ -29406,10 +30767,8 @@ struct unixFile {
sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */
void *pMapRegion; /* Memory mapped region */
#endif
-#ifdef __QNXNTO__
int sectorSize; /* Device sector size */
int deviceCharacteristics; /* Precomputed device characteristics */
-#endif
#if SQLITE_ENABLE_LOCKING_STYLE
int openFlags; /* The flags specified at open() */
#endif
@@ -29712,6 +31071,20 @@ SQLITE_API extern int sqlite3_open_file_count;
# define lseek lseek64
#endif
+#ifdef __linux__
+/*
+** Linux-specific IOCTL magic numbers used for controlling F2FS
+*/
+#define F2FS_IOCTL_MAGIC 0xf5
+#define F2FS_IOC_START_ATOMIC_WRITE _IO(F2FS_IOCTL_MAGIC, 1)
+#define F2FS_IOC_COMMIT_ATOMIC_WRITE _IO(F2FS_IOCTL_MAGIC, 2)
+#define F2FS_IOC_START_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 3)
+#define F2FS_IOC_ABORT_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 5)
+#define F2FS_IOC_GET_FEATURES _IOR(F2FS_IOCTL_MAGIC, 12, u32)
+#define F2FS_FEATURE_ATOMIC_WRITE 0x0004
+#endif /* __linux__ */
+
+
/*
** Different Unix systems declare open() in different ways. Same use
** open(const char*,int,mode_t). Others use open(const char*,int,...).
@@ -29854,7 +31227,7 @@ static struct unix_syscall {
#else
{ "munmap", (sqlite3_syscall_ptr)0, 0 },
#endif
-#define osMunmap ((void*(*)(void*,size_t))aSyscall[23].pCurrent)
+#define osMunmap ((int(*)(void*,size_t))aSyscall[23].pCurrent)
#if HAVE_MREMAP && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)
{ "mremap", (sqlite3_syscall_ptr)mremap, 0 },
@@ -29884,6 +31257,13 @@ static struct unix_syscall {
#endif
#define osLstat ((int(*)(const char*,struct stat*))aSyscall[27].pCurrent)
+#if defined(__linux__) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
+ { "ioctl", (sqlite3_syscall_ptr)ioctl, 0 },
+#else
+ { "ioctl", (sqlite3_syscall_ptr)0, 0 },
+#endif
+#define osIoctl ((int(*)(int,int,...))aSyscall[28].pCurrent)
+
}; /* End of the overrideable system calls */
@@ -30445,7 +31825,14 @@ struct unixFileId {
#if OS_VXWORKS
struct vxworksFileId *pId; /* Unique file ID for vxworks. */
#else
- ino_t ino; /* Inode number */
+ /* We are told that some versions of Android contain a bug that
+ ** sizes ino_t at only 32-bits instead of 64-bits. (See
+ ** https://android-review.googlesource.com/#/c/115351/3/dist/sqlite3.c)
+ ** To work around this, always allocate 64-bits for the inode number.
+ ** On small machines that only have 32-bit inodes, this wastes 4 bytes,
+ ** but that should not be a big deal. */
+ /* WAS: ino_t ino; */
+ u64 ino; /* Inode number */
#endif
};
@@ -30481,7 +31868,8 @@ struct unixInodeInfo {
/*
** A lists of all unixInodeInfo objects.
*/
-static unixInodeInfo *inodeList = 0;
+static unixInodeInfo *inodeList = 0; /* All unixInodeInfo objects */
+static unsigned int nUnusedFd = 0; /* Total unused file descriptors */
/*
**
@@ -30591,6 +31979,7 @@ static void closePendingFds(unixFile *pFile){
pNext = p->pNext;
robust_close(pFile, p->fd, __LINE__);
sqlite3_free(p);
+ nUnusedFd--;
}
pInode->pUnused = 0;
}
@@ -30623,6 +32012,7 @@ static void releaseInodeInfo(unixFile *pFile){
sqlite3_free(pInode);
}
}
+ assert( inodeList!=0 || nUnusedFd==0 );
}
/*
@@ -30690,8 +32080,9 @@ static int findInodeInfo(
#if OS_VXWORKS
fileId.pId = pFile->pId;
#else
- fileId.ino = statbuf.st_ino;
+ fileId.ino = (u64)statbuf.st_ino;
#endif
+ assert( inodeList!=0 || nUnusedFd==0 );
pInode = inodeList;
while( pInode && memcmp(&fileId, &pInode->fileId, sizeof(fileId)) ){
pInode = pInode->pNext;
@@ -30724,7 +32115,8 @@ static int fileHasMoved(unixFile *pFile){
#else
struct stat buf;
return pFile->pInode!=0 &&
- (osStat(pFile->zPath, &buf)!=0 || buf.st_ino!=pFile->pInode->fileId.ino);
+ (osStat(pFile->zPath, &buf)!=0
+ || (u64)buf.st_ino!=pFile->pInode->fileId.ino);
#endif
}
@@ -31110,11 +32502,12 @@ static int unixLock(sqlite3_file *id, int eFileLock){
*/
static void setPendingFd(unixFile *pFile){
unixInodeInfo *pInode = pFile->pInode;
- UnixUnusedFd *p = pFile->pUnused;
+ UnixUnusedFd *p = pFile->pPreallocatedUnused;
p->pNext = pInode->pUnused;
pInode->pUnused = p;
pFile->h = -1;
- pFile->pUnused = 0;
+ pFile->pPreallocatedUnused = 0;
+ nUnusedFd++;
}
/*
@@ -31339,7 +32732,7 @@ static int closeUnixFile(sqlite3_file *id){
#endif
OSTRACE(("CLOSE %-3d\n", pFile->h));
OpenCounter(-1);
- sqlite3_free(pFile->pUnused);
+ sqlite3_free(pFile->pPreallocatedUnused);
memset(pFile, 0, sizeof(unixFile));
return SQLITE_OK;
}
@@ -31676,7 +33069,7 @@ static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){
OSTRACE(("TEST WR-LOCK %d %d %d (flock)\n", pFile->h, rc, reserved));
#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
- if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){
+ if( (rc & 0xff) == SQLITE_IOERR ){
rc = SQLITE_OK;
reserved=1;
}
@@ -31743,7 +33136,7 @@ static int flockLock(sqlite3_file *id, int eFileLock) {
OSTRACE(("LOCK %d %s %s (flock)\n", pFile->h, azFileLock(eFileLock),
rc==SQLITE_OK ? "ok" : "failed"));
#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
- if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){
+ if( (rc & 0xff) == SQLITE_IOERR ){
rc = SQLITE_BUSY;
}
#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
@@ -32280,7 +33673,7 @@ static int afpLock(sqlite3_file *id, int eFileLock){
/* Can't reestablish the shared lock. Sqlite can't deal, this is
** a critical I/O error
*/
- rc = ((failed & SQLITE_IOERR) == SQLITE_IOERR) ? failed2 :
+ rc = ((failed & 0xff) == SQLITE_IOERR) ? failed2 :
SQLITE_IOERR_LOCK;
goto afp_end_lock;
}
@@ -32560,7 +33953,7 @@ static int unixRead(
/* If this is a database file (not a journal, master-journal or temp
** file), the bytes in the locking range should never be read or written. */
#if 0
- assert( pFile->pUnused==0
+ assert( pFile->pPreallocatedUnused==0
|| offset>=PENDING_BYTE+512
|| offset+amt<=PENDING_BYTE
);
@@ -32673,7 +34066,7 @@ static int unixWrite(
/* If this is a database file (not a journal, master-journal or temp
** file), the bytes in the locking range should never be read or written. */
#if 0
- assert( pFile->pUnused==0
+ assert( pFile->pPreallocatedUnused==0
|| offset>=PENDING_BYTE+512
|| offset+amt<=PENDING_BYTE
);
@@ -33153,6 +34546,21 @@ static int unixGetTempname(int nBuf, char *zBuf);
static int unixFileControl(sqlite3_file *id, int op, void *pArg){
unixFile *pFile = (unixFile*)id;
switch( op ){
+#if defined(__linux__) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
+ case SQLITE_FCNTL_BEGIN_ATOMIC_WRITE: {
+ int rc = osIoctl(pFile->h, F2FS_IOC_START_ATOMIC_WRITE);
+ return rc ? SQLITE_IOERR_BEGIN_ATOMIC : SQLITE_OK;
+ }
+ case SQLITE_FCNTL_COMMIT_ATOMIC_WRITE: {
+ int rc = osIoctl(pFile->h, F2FS_IOC_COMMIT_ATOMIC_WRITE);
+ return rc ? SQLITE_IOERR_COMMIT_ATOMIC : SQLITE_OK;
+ }
+ case SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE: {
+ int rc = osIoctl(pFile->h, F2FS_IOC_ABORT_VOLATILE_WRITE);
+ return rc ? SQLITE_IOERR_ROLLBACK_ATOMIC : SQLITE_OK;
+ }
+#endif /* __linux__ && SQLITE_ENABLE_BATCH_ATOMIC_WRITE */
+
case SQLITE_FCNTL_LOCKSTATE: {
*(int*)pArg = pFile->eFileLock;
return SQLITE_OK;
@@ -33203,6 +34611,14 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
if( newLimit>sqlite3GlobalConfig.mxMmap ){
newLimit = sqlite3GlobalConfig.mxMmap;
}
+
+ /* The value of newLimit may be eventually cast to (size_t) and passed
+ ** to mmap(). Restrict its value to 2GB if (size_t) is not at least a
+ ** 64-bit type. */
+ if( newLimit>0 && sizeof(size_t)<8 ){
+ newLimit = (newLimit & 0x7FFFFFFF);
+ }
+
*(i64*)pArg = pFile->mmapSizeMax;
if( newLimit>=0 && newLimit!=pFile->mmapSizeMax && pFile->nFetchOut==0 ){
pFile->mmapSizeMax = newLimit;
@@ -33236,30 +34652,41 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
}
/*
-** Return the sector size in bytes of the underlying block device for
-** the specified file. This is almost always 512 bytes, but may be
-** larger for some devices.
+** If pFd->sectorSize is non-zero when this function is called, it is a
+** no-op. Otherwise, the values of pFd->sectorSize and
+** pFd->deviceCharacteristics are set according to the file-system
+** characteristics.
**
-** SQLite code assumes this function cannot fail. It also assumes that
-** if two files are created in the same file-system directory (i.e.
-** a database and its journal file) that the sector size will be the
-** same for both.
+** There are two versions of this function. One for QNX and one for all
+** other systems.
*/
-#ifndef __QNXNTO__
-static int unixSectorSize(sqlite3_file *NotUsed){
- UNUSED_PARAMETER(NotUsed);
- return SQLITE_DEFAULT_SECTOR_SIZE;
-}
-#endif
+#ifndef __QNXNTO__
+static void setDeviceCharacteristics(unixFile *pFd){
+ assert( pFd->deviceCharacteristics==0 || pFd->sectorSize!=0 );
+ if( pFd->sectorSize==0 ){
+#if defined(__linux__) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
+ int res;
+ u32 f = 0;
-/*
-** The following version of unixSectorSize() is optimized for QNX.
-*/
-#ifdef __QNXNTO__
+ /* Check for support for F2FS atomic batch writes. */
+ res = osIoctl(pFd->h, F2FS_IOC_GET_FEATURES, &f);
+ if( res==0 && (f & F2FS_FEATURE_ATOMIC_WRITE) ){
+ pFd->deviceCharacteristics = SQLITE_IOCAP_BATCH_ATOMIC;
+ }
+#endif /* __linux__ && SQLITE_ENABLE_BATCH_ATOMIC_WRITE */
+
+ /* Set the POWERSAFE_OVERWRITE flag if requested. */
+ if( pFd->ctrlFlags & UNIXFILE_PSOW ){
+ pFd->deviceCharacteristics |= SQLITE_IOCAP_POWERSAFE_OVERWRITE;
+ }
+
+ pFd->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
+ }
+}
+#else
#include
#include
-static int unixSectorSize(sqlite3_file *id){
- unixFile *pFile = (unixFile*)id;
+static void setDeviceCharacteristics(unixFile *pFile){
if( pFile->sectorSize == 0 ){
struct statvfs fsInfo;
@@ -33267,7 +34694,7 @@ static int unixSectorSize(sqlite3_file *id){
pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
pFile->deviceCharacteristics = 0;
if( fstatvfs(pFile->h, &fsInfo) == -1 ) {
- return pFile->sectorSize;
+ return;
}
if( !strcmp(fsInfo.f_basetype, "tmp") ) {
@@ -33328,9 +34755,24 @@ static int unixSectorSize(sqlite3_file *id){
pFile->deviceCharacteristics = 0;
pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
}
- return pFile->sectorSize;
}
-#endif /* __QNXNTO__ */
+#endif
+
+/*
+** Return the sector size in bytes of the underlying block device for
+** the specified file. This is almost always 512 bytes, but may be
+** larger for some devices.
+**
+** SQLite code assumes this function cannot fail. It also assumes that
+** if two files are created in the same file-system directory (i.e.
+** a database and its journal file) that the sector size will be the
+** same for both.
+*/
+static int unixSectorSize(sqlite3_file *id){
+ unixFile *pFd = (unixFile*)id;
+ setDeviceCharacteristics(pFd);
+ return pFd->sectorSize;
+}
/*
** Return the device characteristics for the file.
@@ -33346,16 +34788,9 @@ static int unixSectorSize(sqlite3_file *id){
** available to turn it off and URI query parameter available to turn it off.
*/
static int unixDeviceCharacteristics(sqlite3_file *id){
- unixFile *p = (unixFile*)id;
- int rc = 0;
-#ifdef __QNXNTO__
- if( p->sectorSize==0 ) unixSectorSize(id);
- rc = p->deviceCharacteristics;
-#endif
- if( p->ctrlFlags & UNIXFILE_PSOW ){
- rc |= SQLITE_IOCAP_POWERSAFE_OVERWRITE;
- }
- return rc;
+ unixFile *pFd = (unixFile*)id;
+ setDeviceCharacteristics(pFd);
+ return pFd->deviceCharacteristics;
}
#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
@@ -33417,6 +34852,7 @@ struct unixShmNode {
int szRegion; /* Size of shared-memory regions */
u16 nRegion; /* Size of array apRegion */
u8 isReadonly; /* True if read-only */
+ u8 isUnlocked; /* True if no DMS lock held */
char **apRegion; /* Array of mapped shared-memory regions */
int nRef; /* Number of unixShm objects pointing to this */
unixShm *pFirst; /* All unixShm objects pointing to this */
@@ -33473,7 +34909,7 @@ static int unixShmSystemLock(
/* Access to the unixShmNode object is serialized by the caller */
pShmNode = pFile->pInode->pShmNode;
- assert( sqlite3_mutex_held(pShmNode->mutex) || pShmNode->nRef==0 );
+ assert( pShmNode->nRef==0 || sqlite3_mutex_held(pShmNode->mutex) );
/* Shared locks never span more than one byte */
assert( n==1 || lockType!=F_RDLCK );
@@ -33579,6 +35015,64 @@ static void unixShmPurge(unixFile *pFd){
}
}
+/*
+** The DMS lock has not yet been taken on shm file pShmNode. Attempt to
+** take it now. Return SQLITE_OK if successful, or an SQLite error
+** code otherwise.
+**
+** If the DMS cannot be locked because this is a readonly_shm=1
+** connection and no other process already holds a lock, return
+** SQLITE_READONLY_CANTINIT and set pShmNode->isUnlocked=1.
+*/
+static int unixLockSharedMemory(unixFile *pDbFd, unixShmNode *pShmNode){
+ struct flock lock;
+ int rc = SQLITE_OK;
+
+ /* Use F_GETLK to determine the locks other processes are holding
+ ** on the DMS byte. If it indicates that another process is holding
+ ** a SHARED lock, then this process may also take a SHARED lock
+ ** and proceed with opening the *-shm file.
+ **
+ ** Or, if no other process is holding any lock, then this process
+ ** is the first to open it. In this case take an EXCLUSIVE lock on the
+ ** DMS byte and truncate the *-shm file to zero bytes in size. Then
+ ** downgrade to a SHARED lock on the DMS byte.
+ **
+ ** If another process is holding an EXCLUSIVE lock on the DMS byte,
+ ** return SQLITE_BUSY to the caller (it will try again). An earlier
+ ** version of this code attempted the SHARED lock at this point. But
+ ** this introduced a subtle race condition: if the process holding
+ ** EXCLUSIVE failed just before truncating the *-shm file, then this
+ ** process might open and use the *-shm file without truncating it.
+ ** And if the *-shm file has been corrupted by a power failure or
+ ** system crash, the database itself may also become corrupt. */
+ lock.l_whence = SEEK_SET;
+ lock.l_start = UNIX_SHM_DMS;
+ lock.l_len = 1;
+ lock.l_type = F_WRLCK;
+ if( osFcntl(pShmNode->h, F_GETLK, &lock)!=0 ) {
+ rc = SQLITE_IOERR_LOCK;
+ }else if( lock.l_type==F_UNLCK ){
+ if( pShmNode->isReadonly ){
+ pShmNode->isUnlocked = 1;
+ rc = SQLITE_READONLY_CANTINIT;
+ }else{
+ rc = unixShmSystemLock(pDbFd, F_WRLCK, UNIX_SHM_DMS, 1);
+ if( rc==SQLITE_OK && robust_ftruncate(pShmNode->h, 0) ){
+ rc = unixLogError(SQLITE_IOERR_SHMOPEN,"ftruncate",pShmNode->zFilename);
+ }
+ }
+ }else if( lock.l_type==F_WRLCK ){
+ rc = SQLITE_BUSY;
+ }
+
+ if( rc==SQLITE_OK ){
+ assert( lock.l_type==F_UNLCK || lock.l_type==F_RDLCK );
+ rc = unixShmSystemLock(pDbFd, F_RDLCK, UNIX_SHM_DMS, 1);
+ }
+ return rc;
+}
+
/*
** Open a shared-memory area associated with open database file pDbFd.
** This particular implementation uses mmapped files.
@@ -33617,9 +35111,9 @@ static void unixShmPurge(unixFile *pFd){
static int unixOpenSharedMemory(unixFile *pDbFd){
struct unixShm *p = 0; /* The connection to be opened */
struct unixShmNode *pShmNode; /* The underlying mmapped file */
- int rc; /* Result code */
+ int rc = SQLITE_OK; /* Result code */
unixInodeInfo *pInode; /* The inode of fd */
- char *zShmFilename; /* Name of the file used for SHM */
+ char *zShm; /* Name of the file used for SHM */
int nShmFilename; /* Size of the SHM filename in bytes */
/* Allocate space for the new unixShm object. */
@@ -33660,14 +35154,14 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
goto shm_open_err;
}
memset(pShmNode, 0, sizeof(*pShmNode)+nShmFilename);
- zShmFilename = pShmNode->zFilename = (char*)&pShmNode[1];
+ zShm = pShmNode->zFilename = (char*)&pShmNode[1];
#ifdef SQLITE_SHM_DIRECTORY
- sqlite3_snprintf(nShmFilename, zShmFilename,
+ sqlite3_snprintf(nShmFilename, zShm,
SQLITE_SHM_DIRECTORY "/sqlite-shm-%x-%x",
(u32)sStat.st_ino, (u32)sStat.st_dev);
#else
- sqlite3_snprintf(nShmFilename, zShmFilename, "%s-shm", zBasePath);
- sqlite3FileSuffix3(pDbFd->zPath, zShmFilename);
+ sqlite3_snprintf(nShmFilename, zShm, "%s-shm", zBasePath);
+ sqlite3FileSuffix3(pDbFd->zPath, zShm);
#endif
pShmNode->h = -1;
pDbFd->pInode->pShmNode = pShmNode;
@@ -33681,15 +35175,16 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
}
if( pInode->bProcessLock==0 ){
- int openFlags = O_RDWR | O_CREAT;
- if( sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){
- openFlags = O_RDONLY;
- pShmNode->isReadonly = 1;
+ if( 0==sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){
+ pShmNode->h = robust_open(zShm, O_RDWR|O_CREAT, (sStat.st_mode&0777));
}
- pShmNode->h = robust_open(zShmFilename, openFlags, (sStat.st_mode&0777));
if( pShmNode->h<0 ){
- rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShmFilename);
- goto shm_open_err;
+ pShmNode->h = robust_open(zShm, O_RDONLY, (sStat.st_mode&0777));
+ if( pShmNode->h<0 ){
+ rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShm);
+ goto shm_open_err;
+ }
+ pShmNode->isReadonly = 1;
}
/* If this process is running as root, make sure that the SHM file
@@ -33697,20 +35192,9 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
** the original owner will not be able to connect.
*/
robustFchown(pShmNode->h, sStat.st_uid, sStat.st_gid);
-
- /* Check to see if another process is holding the dead-man switch.
- ** If not, truncate the file to zero length.
- */
- rc = SQLITE_OK;
- if( unixShmSystemLock(pDbFd, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){
- if( robust_ftruncate(pShmNode->h, 0) ){
- rc = unixLogError(SQLITE_IOERR_SHMOPEN, "ftruncate", zShmFilename);
- }
- }
- if( rc==SQLITE_OK ){
- rc = unixShmSystemLock(pDbFd, F_RDLCK, UNIX_SHM_DMS, 1);
- }
- if( rc ) goto shm_open_err;
+
+ rc = unixLockSharedMemory(pDbFd, pShmNode);
+ if( rc!=SQLITE_OK && rc!=SQLITE_READONLY_CANTINIT ) goto shm_open_err;
}
}
@@ -33734,7 +35218,7 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
p->pNext = pShmNode->pFirst;
pShmNode->pFirst = p;
sqlite3_mutex_leave(pShmNode->mutex);
- return SQLITE_OK;
+ return rc;
/* Jump here on any error */
shm_open_err:
@@ -33786,6 +35270,11 @@ static int unixShmMap(
p = pDbFd->pShm;
pShmNode = p->pShmNode;
sqlite3_mutex_enter(pShmNode->mutex);
+ if( pShmNode->isUnlocked ){
+ rc = unixLockSharedMemory(pDbFd, pShmNode);
+ if( rc!=SQLITE_OK ) goto shmpage_out;
+ pShmNode->isUnlocked = 0;
+ }
assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
assert( pShmNode->pInode==pDbFd->pInode );
assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 );
@@ -34613,17 +36102,6 @@ static int fillInUnixFile(
assert( pNew->pInode==NULL );
- /* Usually the path zFilename should not be a relative pathname. The
- ** exception is when opening the proxy "conch" file in builds that
- ** include the special Apple locking styles.
- */
-#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
- assert( zFilename==0 || zFilename[0]=='/'
- || pVfs->pAppData==(void*)&autolockIoFinder );
-#else
- assert( zFilename==0 || zFilename[0]=='/' );
-#endif
-
/* No locking occurs in temporary files */
assert( zFilename!=0 || (ctrlFlags & UNIXFILE_NOLOCK)!=0 );
@@ -34882,6 +36360,8 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){
#if !OS_VXWORKS
struct stat sStat; /* Results of stat() call */
+ unixEnterMutex();
+
/* A stat() call may fail for various reasons. If this happens, it is
** almost certain that an open() call on the same path will also fail.
** For this reason, if an error occurs in the stat() call here, it is
@@ -34890,13 +36370,12 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){
**
** Even if a subsequent open() call does succeed, the consequences of
** not searching for a reusable file descriptor are not dire. */
- if( 0==osStat(zPath, &sStat) ){
+ if( nUnusedFd>0 && 0==osStat(zPath, &sStat) ){
unixInodeInfo *pInode;
- unixEnterMutex();
pInode = inodeList;
while( pInode && (pInode->fileId.dev!=sStat.st_dev
- || pInode->fileId.ino!=sStat.st_ino) ){
+ || pInode->fileId.ino!=(u64)sStat.st_ino) ){
pInode = pInode->pNext;
}
if( pInode ){
@@ -34904,11 +36383,12 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){
for(pp=&pInode->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext));
pUnused = *pp;
if( pUnused ){
+ nUnusedFd--;
*pp = pUnused->pNext;
}
}
- unixLeaveMutex();
}
+ unixLeaveMutex();
#endif /* if !OS_VXWORKS */
return pUnused;
}
@@ -34984,16 +36464,11 @@ static int findCreateFileMode(
*/
nDb = sqlite3Strlen30(zPath) - 1;
while( zPath[nDb]!='-' ){
-#ifndef SQLITE_ENABLE_8_3_NAMES
- /* In the normal case (8+3 filenames disabled) the journal filename
- ** is guaranteed to contain a '-' character. */
- assert( nDb>0 );
- assert( sqlite3Isalnum(zPath[nDb]) );
-#else
- /* If 8+3 names are possible, then the journal file might not contain
- ** a '-' character. So check for that case and return early. */
+ /* In normal operation, the journal file name will always contain
+ ** a '-' character. However in 8+3 filename mode, or if a corrupt
+ ** rollback journal specifies a master journal with a goofy name, then
+ ** the '-' might be missing. */
if( nDb==0 || zPath[nDb]=='.' ) return SQLITE_OK;
-#endif
nDb--;
}
memcpy(zDb, zPath, nDb);
@@ -35068,7 +36543,7 @@ static int unixOpen(
** a file-descriptor on the directory too. The first time unixSync()
** is called the directory file descriptor will be fsync()ed and close()d.
*/
- int syncDir = (isCreate && (
+ int isNewJrnl = (isCreate && (
eType==SQLITE_OPEN_MASTER_JOURNAL
|| eType==SQLITE_OPEN_MAIN_JOURNAL
|| eType==SQLITE_OPEN_WAL
@@ -35129,7 +36604,7 @@ static int unixOpen(
return SQLITE_NOMEM_BKPT;
}
}
- p->pUnused = pUnused;
+ p->pPreallocatedUnused = pUnused;
/* Database filenames are double-zero terminated if they are not
** URIs with parameters. Hence, they can always be passed into
@@ -35138,7 +36613,7 @@ static int unixOpen(
}else if( !zName ){
/* If zName is NULL, the upper layer is requesting a temp file. */
- assert(isDelete && !syncDir);
+ assert(isDelete && !isNewJrnl);
rc = unixGetTempname(pVfs->mxPathname, zTmpname);
if( rc!=SQLITE_OK ){
return rc;
@@ -35166,24 +36641,31 @@ static int unixOpen(
gid_t gid; /* Groupid for the file */
rc = findCreateFileMode(zName, flags, &openMode, &uid, &gid);
if( rc!=SQLITE_OK ){
- assert( !p->pUnused );
+ assert( !p->pPreallocatedUnused );
assert( eType==SQLITE_OPEN_WAL || eType==SQLITE_OPEN_MAIN_JOURNAL );
return rc;
}
fd = robust_open(zName, openFlags, openMode);
OSTRACE(("OPENX %-3d %s 0%o\n", fd, zName, openFlags));
assert( !isExclusive || (openFlags & O_CREAT)!=0 );
- if( fd<0 && errno!=EISDIR && isReadWrite ){
- /* Failed to open the file for read/write access. Try read-only. */
- flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
- openFlags &= ~(O_RDWR|O_CREAT);
- flags |= SQLITE_OPEN_READONLY;
- openFlags |= O_RDONLY;
- isReadonly = 1;
- fd = robust_open(zName, openFlags, openMode);
+ if( fd<0 ){
+ if( isNewJrnl && errno==EACCES && osAccess(zName, F_OK) ){
+ /* If unable to create a journal because the directory is not
+ ** writable, change the error code to indicate that. */
+ rc = SQLITE_READONLY_DIRECTORY;
+ }else if( errno!=EISDIR && isReadWrite ){
+ /* Failed to open the file for read/write access. Try read-only. */
+ flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
+ openFlags &= ~(O_RDWR|O_CREAT);
+ flags |= SQLITE_OPEN_READONLY;
+ openFlags |= O_RDONLY;
+ isReadonly = 1;
+ fd = robust_open(zName, openFlags, openMode);
+ }
}
if( fd<0 ){
- rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName);
+ int rc2 = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName);
+ if( rc==SQLITE_OK ) rc = rc2;
goto open_finished;
}
@@ -35200,9 +36682,9 @@ static int unixOpen(
*pOutFlags = flags;
}
- if( p->pUnused ){
- p->pUnused->fd = fd;
- p->pUnused->flags = flags;
+ if( p->pPreallocatedUnused ){
+ p->pPreallocatedUnused->fd = fd;
+ p->pPreallocatedUnused->flags = flags;
}
if( isDelete ){
@@ -35243,7 +36725,7 @@ static int unixOpen(
if( isReadonly ) ctrlFlags |= UNIXFILE_RDONLY;
noLock = eType!=SQLITE_OPEN_MAIN_DB;
if( noLock ) ctrlFlags |= UNIXFILE_NOLOCK;
- if( syncDir ) ctrlFlags |= UNIXFILE_DIRSYNC;
+ if( isNewJrnl ) ctrlFlags |= UNIXFILE_DIRSYNC;
if( flags & SQLITE_OPEN_URI ) ctrlFlags |= UNIXFILE_URI;
#if SQLITE_ENABLE_LOCKING_STYLE
@@ -35279,11 +36761,14 @@ static int unixOpen(
}
#endif
+ assert( zPath==0 || zPath[0]=='/'
+ || eType==SQLITE_OPEN_MASTER_JOURNAL || eType==SQLITE_OPEN_MAIN_JOURNAL
+ );
rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags);
open_finished:
if( rc!=SQLITE_OK ){
- sqlite3_free(p->pUnused);
+ sqlite3_free(p->pPreallocatedUnused);
}
return rc;
}
@@ -36024,7 +37509,7 @@ static int proxyCreateUnixFile(
dummyVfs.zName = "dummy";
pUnused->fd = fd;
pUnused->flags = openFlags;
- pNew->pUnused = pUnused;
+ pNew->pPreallocatedUnused = pUnused;
rc = fillInUnixFile(&dummyVfs, fd, (sqlite3_file*)pNew, path, 0);
if( rc==SQLITE_OK ){
@@ -36974,7 +38459,7 @@ SQLITE_API int sqlite3_os_init(void){
/* Double-check that the aSyscall[] array has been constructed
** correctly. See ticket [bb3a86e890c8e96ab] */
- assert( ArraySize(aSyscall)==28 );
+ assert( ArraySize(aSyscall)==29 );
/* Register all VFSes defined in the aVfs[] array */
for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
@@ -37550,7 +39035,34 @@ struct winVfsAppData {
******************************************************************************
*/
#ifndef SQLITE_WIN32_HEAP_CREATE
-# define SQLITE_WIN32_HEAP_CREATE (TRUE)
+# define SQLITE_WIN32_HEAP_CREATE (TRUE)
+#endif
+
+/*
+ * This is the maximum possible initial size of the Win32-specific heap, in
+ * bytes.
+ */
+#ifndef SQLITE_WIN32_HEAP_MAX_INIT_SIZE
+# define SQLITE_WIN32_HEAP_MAX_INIT_SIZE (4294967295U)
+#endif
+
+/*
+ * This is the extra space for the initial size of the Win32-specific heap,
+ * in bytes. This value may be zero.
+ */
+#ifndef SQLITE_WIN32_HEAP_INIT_EXTRA
+# define SQLITE_WIN32_HEAP_INIT_EXTRA (4194304)
+#endif
+
+/*
+ * Calculate the maximum legal cache size, in pages, based on the maximum
+ * possible initial heap size and the default page size, setting aside the
+ * needed extra space.
+ */
+#ifndef SQLITE_WIN32_MAX_CACHE_SIZE
+# define SQLITE_WIN32_MAX_CACHE_SIZE (((SQLITE_WIN32_HEAP_MAX_INIT_SIZE) - \
+ (SQLITE_WIN32_HEAP_INIT_EXTRA)) / \
+ (SQLITE_DEFAULT_PAGE_SIZE))
#endif
/*
@@ -37559,25 +39071,36 @@ struct winVfsAppData {
*/
#ifndef SQLITE_WIN32_CACHE_SIZE
# if SQLITE_DEFAULT_CACHE_SIZE>=0
-# define SQLITE_WIN32_CACHE_SIZE (SQLITE_DEFAULT_CACHE_SIZE)
+# define SQLITE_WIN32_CACHE_SIZE (SQLITE_DEFAULT_CACHE_SIZE)
# else
-# define SQLITE_WIN32_CACHE_SIZE (-(SQLITE_DEFAULT_CACHE_SIZE))
+# define SQLITE_WIN32_CACHE_SIZE (-(SQLITE_DEFAULT_CACHE_SIZE))
# endif
#endif
+/*
+ * Make sure that the calculated cache size, in pages, cannot cause the
+ * initial size of the Win32-specific heap to exceed the maximum amount
+ * of memory that can be specified in the call to HeapCreate.
+ */
+#if SQLITE_WIN32_CACHE_SIZE>SQLITE_WIN32_MAX_CACHE_SIZE
+# undef SQLITE_WIN32_CACHE_SIZE
+# define SQLITE_WIN32_CACHE_SIZE (2000)
+#endif
+
/*
* The initial size of the Win32-specific heap. This value may be zero.
*/
#ifndef SQLITE_WIN32_HEAP_INIT_SIZE
-# define SQLITE_WIN32_HEAP_INIT_SIZE ((SQLITE_WIN32_CACHE_SIZE) * \
- (SQLITE_DEFAULT_PAGE_SIZE) + 4194304)
+# define SQLITE_WIN32_HEAP_INIT_SIZE ((SQLITE_WIN32_CACHE_SIZE) * \
+ (SQLITE_DEFAULT_PAGE_SIZE) + \
+ (SQLITE_WIN32_HEAP_INIT_EXTRA))
#endif
/*
* The maximum size of the Win32-specific heap. This value may be zero.
*/
#ifndef SQLITE_WIN32_HEAP_MAX_SIZE
-# define SQLITE_WIN32_HEAP_MAX_SIZE (0)
+# define SQLITE_WIN32_HEAP_MAX_SIZE (0)
#endif
/*
@@ -37585,7 +39108,7 @@ struct winVfsAppData {
* zero for the default behavior.
*/
#ifndef SQLITE_WIN32_HEAP_FLAGS
-# define SQLITE_WIN32_HEAP_FLAGS (0)
+# define SQLITE_WIN32_HEAP_FLAGS (0)
#endif
@@ -40719,6 +42242,14 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){
if( newLimit>sqlite3GlobalConfig.mxMmap ){
newLimit = sqlite3GlobalConfig.mxMmap;
}
+
+ /* The value of newLimit may be eventually cast to (SIZE_T) and passed
+ ** to MapViewOfFile(). Restrict its value to 2GB if (SIZE_T) is not at
+ ** least a 64-bit type. */
+ if( newLimit>0 && sizeof(SIZE_T)<8 ){
+ newLimit = (newLimit & 0x7FFFFFFF);
+ }
+
*(i64*)pArg = pFile->mmapSizeMax;
if( newLimit>=0 && newLimit!=pFile->mmapSizeMax && pFile->nFetchOut==0 ){
pFile->mmapSizeMax = newLimit;
@@ -40825,6 +42356,9 @@ struct winShmNode {
int szRegion; /* Size of shared-memory regions */
int nRegion; /* Size of array apRegion */
+ u8 isReadonly; /* True if read-only */
+ u8 isUnlocked; /* True if no DMS lock held */
+
struct ShmRegion {
HANDLE hMap; /* File handle from CreateFileMapping */
void *pMap;
@@ -40891,7 +42425,7 @@ static int winShmSystemLock(
int rc = 0; /* Result code form Lock/UnlockFileEx() */
/* Access to the winShmNode object is serialized by the caller */
- assert( sqlite3_mutex_held(pFile->mutex) || pFile->nRef==0 );
+ assert( pFile->nRef==0 || sqlite3_mutex_held(pFile->mutex) );
OSTRACE(("SHM-LOCK file=%p, lock=%d, offset=%d, size=%d\n",
pFile->hFile.h, lockType, ofst, nByte));
@@ -40972,6 +42506,37 @@ static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
}
}
+/*
+** The DMS lock has not yet been taken on shm file pShmNode. Attempt to
+** take it now. Return SQLITE_OK if successful, or an SQLite error
+** code otherwise.
+**
+** If the DMS cannot be locked because this is a readonly_shm=1
+** connection and no other process already holds a lock, return
+** SQLITE_READONLY_CANTINIT and set pShmNode->isUnlocked=1.
+*/
+static int winLockSharedMemory(winShmNode *pShmNode){
+ int rc = winShmSystemLock(pShmNode, WINSHM_WRLCK, WIN_SHM_DMS, 1);
+
+ if( rc==SQLITE_OK ){
+ if( pShmNode->isReadonly ){
+ pShmNode->isUnlocked = 1;
+ winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1);
+ return SQLITE_READONLY_CANTINIT;
+ }else if( winTruncate((sqlite3_file*)&pShmNode->hFile, 0) ){
+ winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1);
+ return winLogError(SQLITE_IOERR_SHMOPEN, osGetLastError(),
+ "winLockSharedMemory", pShmNode->zFilename);
+ }
+ }
+
+ if( rc==SQLITE_OK ){
+ winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1);
+ }
+
+ return winShmSystemLock(pShmNode, WINSHM_RDLCK, WIN_SHM_DMS, 1);
+}
+
/*
** Open the shared-memory area associated with database file pDbFd.
**
@@ -40981,9 +42546,9 @@ static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
*/
static int winOpenSharedMemory(winFile *pDbFd){
struct winShm *p; /* The connection to be opened */
- struct winShmNode *pShmNode = 0; /* The underlying mmapped file */
- int rc; /* Result code */
- struct winShmNode *pNew; /* Newly allocated winShmNode */
+ winShmNode *pShmNode = 0; /* The underlying mmapped file */
+ int rc = SQLITE_OK; /* Result code */
+ winShmNode *pNew; /* Newly allocated winShmNode */
int nName; /* Size of zName in bytes */
assert( pDbFd->pShm==0 ); /* Not previously opened */
@@ -41016,6 +42581,9 @@ static int winOpenSharedMemory(winFile *pDbFd){
if( pShmNode ){
sqlite3_free(pNew);
}else{
+ int inFlags = SQLITE_OPEN_WAL;
+ int outFlags = 0;
+
pShmNode = pNew;
pNew = 0;
((winFile*)(&pShmNode->hFile))->h = INVALID_HANDLE_VALUE;
@@ -41030,30 +42598,23 @@ static int winOpenSharedMemory(winFile *pDbFd){
}
}
- rc = winOpen(pDbFd->pVfs,
- pShmNode->zFilename, /* Name of the file (UTF-8) */
- (sqlite3_file*)&pShmNode->hFile, /* File handle here */
- SQLITE_OPEN_WAL | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
- 0);
- if( SQLITE_OK!=rc ){
+ if( 0==sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){
+ inFlags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
+ }else{
+ inFlags |= SQLITE_OPEN_READONLY;
+ }
+ rc = winOpen(pDbFd->pVfs, pShmNode->zFilename,
+ (sqlite3_file*)&pShmNode->hFile,
+ inFlags, &outFlags);
+ if( rc!=SQLITE_OK ){
+ rc = winLogError(rc, osGetLastError(), "winOpenShm",
+ pShmNode->zFilename);
goto shm_open_err;
}
+ if( outFlags==SQLITE_OPEN_READONLY ) pShmNode->isReadonly = 1;
- /* Check to see if another process is holding the dead-man switch.
- ** If not, truncate the file to zero length.
- */
- if( winShmSystemLock(pShmNode, WINSHM_WRLCK, WIN_SHM_DMS, 1)==SQLITE_OK ){
- rc = winTruncate((sqlite3_file *)&pShmNode->hFile, 0);
- if( rc!=SQLITE_OK ){
- rc = winLogError(SQLITE_IOERR_SHMOPEN, osGetLastError(),
- "winOpenShm", pDbFd->zPath);
- }
- }
- if( rc==SQLITE_OK ){
- winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1);
- rc = winShmSystemLock(pShmNode, WINSHM_RDLCK, WIN_SHM_DMS, 1);
- }
- if( rc ) goto shm_open_err;
+ rc = winLockSharedMemory(pShmNode);
+ if( rc!=SQLITE_OK && rc!=SQLITE_READONLY_CANTINIT ) goto shm_open_err;
}
/* Make the new connection a child of the winShmNode */
@@ -41076,7 +42637,7 @@ static int winOpenSharedMemory(winFile *pDbFd){
p->pNext = pShmNode->pFirst;
pShmNode->pFirst = p;
sqlite3_mutex_leave(pShmNode->mutex);
- return SQLITE_OK;
+ return rc;
/* Jump here on any error */
shm_open_err:
@@ -41280,6 +42841,8 @@ static int winShmMap(
winFile *pDbFd = (winFile*)fd;
winShm *pShm = pDbFd->pShm;
winShmNode *pShmNode;
+ DWORD protect = PAGE_READWRITE;
+ DWORD flags = FILE_MAP_WRITE | FILE_MAP_READ;
int rc = SQLITE_OK;
if( !pShm ){
@@ -41290,6 +42853,11 @@ static int winShmMap(
pShmNode = pShm->pShmNode;
sqlite3_mutex_enter(pShmNode->mutex);
+ if( pShmNode->isUnlocked ){
+ rc = winLockSharedMemory(pShmNode);
+ if( rc!=SQLITE_OK ) goto shmpage_out;
+ pShmNode->isUnlocked = 0;
+ }
assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
if( pShmNode->nRegion<=iRegion ){
@@ -41336,21 +42904,26 @@ static int winShmMap(
}
pShmNode->aRegion = apNew;
+ if( pShmNode->isReadonly ){
+ protect = PAGE_READONLY;
+ flags = FILE_MAP_READ;
+ }
+
while( pShmNode->nRegion<=iRegion ){
HANDLE hMap = NULL; /* file-mapping handle */
void *pMap = 0; /* Mapped memory region */
#if SQLITE_OS_WINRT
hMap = osCreateFileMappingFromApp(pShmNode->hFile.h,
- NULL, PAGE_READWRITE, nByte, NULL
+ NULL, protect, nByte, NULL
);
#elif defined(SQLITE_WIN32_HAS_WIDE)
hMap = osCreateFileMappingW(pShmNode->hFile.h,
- NULL, PAGE_READWRITE, 0, nByte, NULL
+ NULL, protect, 0, nByte, NULL
);
#elif defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_CREATEFILEMAPPINGA
hMap = osCreateFileMappingA(pShmNode->hFile.h,
- NULL, PAGE_READWRITE, 0, nByte, NULL
+ NULL, protect, 0, nByte, NULL
);
#endif
OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%d, rc=%s\n",
@@ -41360,11 +42933,11 @@ static int winShmMap(
int iOffset = pShmNode->nRegion*szRegion;
int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity;
#if SQLITE_OS_WINRT
- pMap = osMapViewOfFileFromApp(hMap, FILE_MAP_WRITE | FILE_MAP_READ,
+ pMap = osMapViewOfFileFromApp(hMap, flags,
iOffset - iOffsetShift, szRegion + iOffsetShift
);
#else
- pMap = osMapViewOfFile(hMap, FILE_MAP_WRITE | FILE_MAP_READ,
+ pMap = osMapViewOfFile(hMap, flags,
0, iOffset - iOffsetShift, szRegion + iOffsetShift
);
#endif
@@ -41395,6 +42968,7 @@ static int winShmMap(
}else{
*pp = 0;
}
+ if( pShmNode->isReadonly && rc==SQLITE_OK ) rc = SQLITE_READONLY;
sqlite3_mutex_leave(pShmNode->mutex);
return rc;
}
@@ -42031,6 +43605,14 @@ static int winIsDir(const void *zConverted){
return (attr!=INVALID_FILE_ATTRIBUTES) && (attr&FILE_ATTRIBUTE_DIRECTORY);
}
+/* forward reference */
+static int winAccess(
+ sqlite3_vfs *pVfs, /* Not used on win32 */
+ const char *zFilename, /* Name of file to check */
+ int flags, /* Type of test to make on this file */
+ int *pResOut /* OUT: Result */
+);
+
/*
** Open a file.
*/
@@ -42207,37 +43789,58 @@ static int winOpen(
extendedParameters.dwSecurityQosFlags = SECURITY_ANONYMOUS;
extendedParameters.lpSecurityAttributes = NULL;
extendedParameters.hTemplateFile = NULL;
- while( (h = osCreateFile2((LPCWSTR)zConverted,
- dwDesiredAccess,
- dwShareMode,
- dwCreationDisposition,
- &extendedParameters))==INVALID_HANDLE_VALUE &&
- winRetryIoerr(&cnt, &lastErrno) ){
- /* Noop */
- }
+ do{
+ h = osCreateFile2((LPCWSTR)zConverted,
+ dwDesiredAccess,
+ dwShareMode,
+ dwCreationDisposition,
+ &extendedParameters);
+ if( h!=INVALID_HANDLE_VALUE ) break;
+ if( isReadWrite ){
+ int rc2, isRO = 0;
+ sqlite3BeginBenignMalloc();
+ rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO);
+ sqlite3EndBenignMalloc();
+ if( rc2==SQLITE_OK && isRO ) break;
+ }
+ }while( winRetryIoerr(&cnt, &lastErrno) );
#else
- while( (h = osCreateFileW((LPCWSTR)zConverted,
- dwDesiredAccess,
- dwShareMode, NULL,
- dwCreationDisposition,
- dwFlagsAndAttributes,
- NULL))==INVALID_HANDLE_VALUE &&
- winRetryIoerr(&cnt, &lastErrno) ){
- /* Noop */
- }
+ do{
+ h = osCreateFileW((LPCWSTR)zConverted,
+ dwDesiredAccess,
+ dwShareMode, NULL,
+ dwCreationDisposition,
+ dwFlagsAndAttributes,
+ NULL);
+ if( h!=INVALID_HANDLE_VALUE ) break;
+ if( isReadWrite ){
+ int rc2, isRO = 0;
+ sqlite3BeginBenignMalloc();
+ rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO);
+ sqlite3EndBenignMalloc();
+ if( rc2==SQLITE_OK && isRO ) break;
+ }
+ }while( winRetryIoerr(&cnt, &lastErrno) );
#endif
}
#ifdef SQLITE_WIN32_HAS_ANSI
else{
- while( (h = osCreateFileA((LPCSTR)zConverted,
- dwDesiredAccess,
- dwShareMode, NULL,
- dwCreationDisposition,
- dwFlagsAndAttributes,
- NULL))==INVALID_HANDLE_VALUE &&
- winRetryIoerr(&cnt, &lastErrno) ){
- /* Noop */
- }
+ do{
+ h = osCreateFileA((LPCSTR)zConverted,
+ dwDesiredAccess,
+ dwShareMode, NULL,
+ dwCreationDisposition,
+ dwFlagsAndAttributes,
+ NULL);
+ if( h!=INVALID_HANDLE_VALUE ) break;
+ if( isReadWrite ){
+ int rc2, isRO = 0;
+ sqlite3BeginBenignMalloc();
+ rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO);
+ sqlite3EndBenignMalloc();
+ if( rc2==SQLITE_OK && isRO ) break;
+ }
+ }while( winRetryIoerr(&cnt, &lastErrno) );
}
#endif
winLogIoerr(cnt, __LINE__);
@@ -42246,8 +43849,6 @@ static int winOpen(
dwDesiredAccess, (h==INVALID_HANDLE_VALUE) ? "failed" : "ok"));
if( h==INVALID_HANDLE_VALUE ){
- pFile->lastErrno = lastErrno;
- winLogError(SQLITE_CANTOPEN, pFile->lastErrno, "winOpen", zUtf8Name);
sqlite3_free(zConverted);
sqlite3_free(zTmpname);
if( isReadWrite && !isExclusive ){
@@ -42256,6 +43857,8 @@ static int winOpen(
~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)),
pOutFlags);
}else{
+ pFile->lastErrno = lastErrno;
+ winLogError(SQLITE_CANTOPEN, pFile->lastErrno, "winOpen", zUtf8Name);
return SQLITE_CANTOPEN_BKPT;
}
}
@@ -42848,9 +44451,6 @@ static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
EntropyGatherer e;
UNUSED_PARAMETER(pVfs);
memset(zBuf, 0, nBuf);
-#if defined(_MSC_VER) && _MSC_VER>=1400 && !SQLITE_OS_WINCE
- rand_s((unsigned int*)zBuf); /* rand_s() is not available with MinGW */
-#endif /* defined(_MSC_VER) && _MSC_VER>=1400 */
e.a = (unsigned char*)zBuf;
e.na = nBuf;
e.nXor = 0;
@@ -43457,7 +45057,7 @@ SQLITE_PRIVATE u32 sqlite3BitvecSize(Bitvec *p){
return p->iSize;
}
-#ifndef SQLITE_OMIT_BUILTIN_TEST
+#ifndef SQLITE_UNTESTABLE
/*
** 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<=Ipgno>0 ); /* Page number is 1 or more */
+ assert( pPg->pgno>0 || pPg->pPager==0 ); /* Page number is 1 or more */
pCache = pPg->pCache;
assert( pCache!=0 ); /* Every page has an associated PCache */
if( pPg->flags & PGHDR_CLEAN ){
@@ -43769,12 +45369,9 @@ static void pcacheManageDirtyList(PgHdr *pPage, u8 addRemove){
p->eCreate = 2;
}
}
- pPage->pDirtyNext = 0;
- pPage->pDirtyPrev = 0;
}
if( addRemove & PCACHE_DIRTYLIST_ADD ){
- assert( pPage->pDirtyNext==0 && pPage->pDirtyPrev==0 && p->pDirty!=pPage );
-
+ pPage->pDirtyPrev = 0;
pPage->pDirtyNext = p->pDirty;
if( pPage->pDirtyNext ){
assert( pPage->pDirtyNext->pDirtyPrev==0 );
@@ -43862,6 +45459,12 @@ SQLITE_PRIVATE int sqlite3PcacheSize(void){ return sizeof(PCache); }
** has already been allocated and is passed in as the p pointer.
** The caller discovers how much space needs to be allocated by
** calling sqlite3PcacheSize().
+**
+** szExtra is some extra space allocated for each page. The first
+** 8 bytes of the extra space will be zeroed as the page is allocated,
+** but remaining content will be uninitialized. Though it is opaque
+** to this module, the extra space really ends up being the MemPage
+** structure in the pager.
*/
SQLITE_PRIVATE int sqlite3PcacheOpen(
int szPage, /* Size of every page */
@@ -43874,6 +45477,7 @@ SQLITE_PRIVATE int sqlite3PcacheOpen(
memset(p, 0, sizeof(PCache));
p->szPage = 1;
p->szExtra = szExtra;
+ assert( szExtra>=8 ); /* First 8 bytes will be zeroed */
p->bPurgeable = bPurgeable;
p->eCreate = 2;
p->xStress = xStress;
@@ -43943,7 +45547,6 @@ SQLITE_PRIVATE sqlite3_pcache_page *sqlite3PcacheFetch(
assert( pCache!=0 );
assert( pCache->pCache!=0 );
assert( createFlag==3 || createFlag==0 );
- assert( pgno>0 );
assert( pCache->eCreate==((pCache->bPurgeable && pCache->pDirty) ? 1 : 2) );
/* eCreate defines what to do if the page does not exist.
@@ -44043,7 +45646,7 @@ static SQLITE_NOINLINE PgHdr *pcacheFetchFinishWithInit(
pPgHdr->pPage = pPage;
pPgHdr->pData = pPage->pBuf;
pPgHdr->pExtra = (void *)&pPgHdr[1];
- memset(pPgHdr->pExtra, 0, pCache->szExtra);
+ memset(pPgHdr->pExtra, 0, 8);
pPgHdr->pCache = pCache;
pPgHdr->pgno = pgno;
pPgHdr->flags = PGHDR_CLEAN;
@@ -44085,11 +45688,7 @@ SQLITE_PRIVATE void SQLITE_NOINLINE sqlite3PcacheRelease(PgHdr *p){
if( (--p->nRef)==0 ){
if( p->flags&PGHDR_CLEAN ){
pcacheUnpin(p);
- }else if( p->pDirtyPrev!=0 ){ /*OPTIMIZATION-IF-FALSE*/
- /* Move the page to the head of the dirty list. If p->pDirtyPrev==0,
- ** then page p is already at the head of the dirty list and the
- ** following call would be a no-op. Hence the OPTIMIZATION-IF-FALSE
- ** tag above. */
+ }else{
pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT);
}
}
@@ -44145,16 +45744,15 @@ SQLITE_PRIVATE void sqlite3PcacheMakeDirty(PgHdr *p){
*/
SQLITE_PRIVATE void sqlite3PcacheMakeClean(PgHdr *p){
assert( sqlite3PcachePageSanity(p) );
- if( ALWAYS((p->flags & PGHDR_DIRTY)!=0) ){
- assert( (p->flags & PGHDR_CLEAN)==0 );
- pcacheManageDirtyList(p, PCACHE_DIRTYLIST_REMOVE);
- p->flags &= ~(PGHDR_DIRTY|PGHDR_NEED_SYNC|PGHDR_WRITEABLE);
- p->flags |= PGHDR_CLEAN;
- pcacheTrace(("%p.CLEAN %d\n",p->pCache,p->pgno));
- assert( sqlite3PcachePageSanity(p) );
- if( p->nRef==0 ){
- pcacheUnpin(p);
- }
+ assert( (p->flags & PGHDR_DIRTY)!=0 );
+ assert( (p->flags & PGHDR_CLEAN)==0 );
+ pcacheManageDirtyList(p, PCACHE_DIRTYLIST_REMOVE);
+ p->flags &= ~(PGHDR_DIRTY|PGHDR_NEED_SYNC|PGHDR_WRITEABLE);
+ p->flags |= PGHDR_CLEAN;
+ pcacheTrace(("%p.CLEAN %d\n",p->pCache,p->pgno));
+ assert( sqlite3PcachePageSanity(p) );
+ if( p->nRef==0 ){
+ pcacheUnpin(p);
}
}
@@ -44550,7 +46148,6 @@ typedef struct PGroup PGroup;
struct PgHdr1 {
sqlite3_pcache_page page; /* Base class. Must be first. pBuf & pExtra */
unsigned int iKey; /* Key value (page number) */
- u8 isPinned; /* Page in use, not on the LRU list */
u8 isBulkLocal; /* This page from bulk local storage */
u8 isAnchor; /* This is the PGroup.lru element */
PgHdr1 *pNext; /* Next in hash table chain */
@@ -44559,6 +46156,12 @@ struct PgHdr1 {
PgHdr1 *pLruPrev; /* Previous in LRU list of unpinned pages */
};
+/*
+** A page is pinned if it is no on the LRU list
+*/
+#define PAGE_IS_PINNED(p) ((p)->pLruNext==0)
+#define PAGE_IS_UNPINNED(p) ((p)->pLruNext!=0)
+
/* Each page cache (or PCache) belongs to a PGroup. A PGroup is a set
** of one or more PCaches that are able to recycle each other's unpinned
** pages when they are under memory pressure. A PGroup is an instance of
@@ -44586,7 +46189,7 @@ struct PGroup {
unsigned int nMaxPage; /* Sum of nMax for purgeable caches */
unsigned int nMinPage; /* Sum of nMin for purgeable caches */
unsigned int mxPinned; /* nMaxpage + 10 - nMinPage */
- unsigned int nCurrentPage; /* Number of purgeable pages allocated */
+ unsigned int nPurgeable; /* Number of purgeable pages allocated */
PgHdr1 lru; /* The beginning and end of the LRU list */
};
@@ -44600,11 +46203,13 @@ struct PGroup {
*/
struct PCache1 {
/* Cache configuration parameters. Page size (szPage) and the purgeable
- ** flag (bPurgeable) are set when the cache is created. nMax may be
+ ** flag (bPurgeable) and the pnPurgeable pointer are all set when the
+ ** cache is created and are never changed thereafter. nMax may be
** modified at any time by a call to the pcache1Cachesize() method.
** The PGroup mutex must be held when accessing nMax.
*/
PGroup *pGroup; /* PGroup this cache belongs to */
+ unsigned int *pnPurgeable; /* Pointer to pGroup->nPurgeable */
int szPage; /* Size of database content section */
int szExtra; /* sizeof(MemPage)+sizeof(PgHdr) */
int szAlloc; /* Total size of one pcache line */
@@ -44699,6 +46304,7 @@ SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){
if( pcache1.isInit ){
PgFreeslot *p;
if( pBuf==0 ) sz = n = 0;
+ if( n==0 ) sz = 0;
sz = ROUNDDOWN8(sz);
pcache1.szSlot = sz;
pcache1.nSlot = pcache1.nFreeSlot = n;
@@ -44739,8 +46345,7 @@ static int pcache1InitBulk(PCache1 *pCache){
sqlite3EndBenignMalloc();
if( zBulk ){
int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc;
- int i;
- for(i=0; iszPage];
pX->page.pBuf = zBulk;
pX->page.pExtra = &pX[1];
@@ -44749,7 +46354,7 @@ static int pcache1InitBulk(PCache1 *pCache){
pX->pNext = pCache->pFree;
pCache->pFree = pX;
zBulk += pCache->szAlloc;
- }
+ }while( --nBulk );
}
return pCache->pFree!=0;
}
@@ -44892,9 +46497,7 @@ static PgHdr1 *pcache1AllocPage(PCache1 *pCache, int benignMalloc){
p->isBulkLocal = 0;
p->isAnchor = 0;
}
- if( pCache->bPurgeable ){
- pCache->pGroup->nCurrentPage++;
- }
+ (*pCache->pnPurgeable)++;
return p;
}
@@ -44915,9 +46518,7 @@ static void pcache1FreePage(PgHdr1 *p){
sqlite3_free(p);
#endif
}
- if( pCache->bPurgeable ){
- pCache->pGroup->nCurrentPage--;
- }
+ (*pCache->pnPurgeable)--;
}
/*
@@ -45012,22 +46613,18 @@ static void pcache1ResizeHash(PCache1 *p){
** The PGroup mutex must be held when this function is called.
*/
static PgHdr1 *pcache1PinPage(PgHdr1 *pPage){
- PCache1 *pCache;
-
assert( pPage!=0 );
- assert( pPage->isPinned==0 );
- pCache = pPage->pCache;
+ assert( PAGE_IS_UNPINNED(pPage) );
assert( pPage->pLruNext );
assert( pPage->pLruPrev );
- assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
+ assert( sqlite3_mutex_held(pPage->pCache->pGroup->mutex) );
pPage->pLruPrev->pLruNext = pPage->pLruNext;
pPage->pLruNext->pLruPrev = pPage->pLruPrev;
pPage->pLruNext = 0;
pPage->pLruPrev = 0;
- pPage->isPinned = 1;
assert( pPage->isAnchor==0 );
- assert( pCache->pGroup->lru.isAnchor==1 );
- pCache->nRecyclable--;
+ assert( pPage->pCache->pGroup->lru.isAnchor==1 );
+ pPage->pCache->nRecyclable--;
return pPage;
}
@@ -45061,11 +46658,11 @@ static void pcache1EnforceMaxPage(PCache1 *pCache){
PGroup *pGroup = pCache->pGroup;
PgHdr1 *p;
assert( sqlite3_mutex_held(pGroup->mutex) );
- while( pGroup->nCurrentPage>pGroup->nMaxPage
+ while( pGroup->nPurgeable>pGroup->nMaxPage
&& (p=pGroup->lru.pLruPrev)->isAnchor==0
){
assert( p->pCache->pGroup==pGroup );
- assert( p->isPinned==0 );
+ assert( PAGE_IS_UNPINNED(p) );
pcache1PinPage(p);
pcache1RemoveFromHash(p, 1);
}
@@ -45114,7 +46711,7 @@ static void pcache1TruncateUnsafe(
if( pPage->iKey>=iLimit ){
pCache->nPage--;
*pp = pPage->pNext;
- if( !pPage->isPinned ) pcache1PinPage(pPage);
+ if( PAGE_IS_UNPINNED(pPage) ) pcache1PinPage(pPage);
pcache1FreePage(pPage);
}else{
pp = &pPage->pNext;
@@ -45232,6 +46829,10 @@ static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){
pCache->nMin = 10;
pGroup->nMinPage += pCache->nMin;
pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
+ pCache->pnPurgeable = &pGroup->nPurgeable;
+ }else{
+ static unsigned int dummyCurrentPage;
+ pCache->pnPurgeable = &dummyCurrentPage;
}
pcache1LeaveMutex(pGroup);
if( pCache->nHash==0 ){
@@ -45333,7 +46934,7 @@ static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(
){
PCache1 *pOther;
pPage = pGroup->lru.pLruPrev;
- assert( pPage->isPinned==0 );
+ assert( PAGE_IS_UNPINNED(pPage) );
pcache1RemoveFromHash(pPage, 0);
pcache1PinPage(pPage);
pOther = pPage->pCache;
@@ -45341,7 +46942,7 @@ static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(
pcache1FreePage(pPage);
pPage = 0;
}else{
- pGroup->nCurrentPage -= (pOther->bPurgeable - pCache->bPurgeable);
+ pGroup->nPurgeable -= (pOther->bPurgeable - pCache->bPurgeable);
}
}
@@ -45360,7 +46961,6 @@ static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(
pPage->pCache = pCache;
pPage->pLruPrev = 0;
pPage->pLruNext = 0;
- pPage->isPinned = 1;
*(void **)pPage->page.pExtra = 0;
pCache->apHash[h] = pPage;
if( iKey>pCache->iMaxKey ){
@@ -45446,7 +47046,7 @@ static PgHdr1 *pcache1FetchNoMutex(
** Otherwise (page not in hash and createFlag!=0) continue with
** subsequent steps to try to create the page. */
if( pPage ){
- if( !pPage->isPinned ){
+ if( PAGE_IS_UNPINNED(pPage) ){
return pcache1PinPage(pPage);
}else{
return pPage;
@@ -45521,9 +47121,9 @@ static void pcache1Unpin(
** part of the PGroup LRU list.
*/
assert( pPage->pLruPrev==0 && pPage->pLruNext==0 );
- assert( pPage->isPinned==1 );
+ assert( PAGE_IS_PINNED(pPage) );
- if( reuseUnlikely || pGroup->nCurrentPage>pGroup->nMaxPage ){
+ if( reuseUnlikely || pGroup->nPurgeable>pGroup->nMaxPage ){
pcache1RemoveFromHash(pPage, 1);
}else{
/* Add the page to the PGroup LRU list. */
@@ -45532,7 +47132,6 @@ static void pcache1Unpin(
(pPage->pLruNext = *ppFirst)->pLruPrev = pPage;
*ppFirst = pPage;
pCache->nRecyclable++;
- pPage->isPinned = 0;
}
pcache1LeaveMutex(pCache->pGroup);
@@ -45665,7 +47264,7 @@ SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int nReq){
int nFree = 0;
assert( sqlite3_mutex_notheld(pcache1.grp.mutex) );
assert( sqlite3_mutex_notheld(pcache1.mutex) );
- if( sqlite3GlobalConfig.nPage==0 ){
+ if( sqlite3GlobalConfig.pPage==0 ){
PgHdr1 *p;
pcache1EnterMutex(&pcache1.grp);
while( (nReq<0 || nFreeisPinned==0 );
+ assert( PAGE_IS_UNPINNED(p) );
pcache1PinPage(p);
pcache1RemoveFromHash(p, 1);
}
@@ -45700,10 +47299,10 @@ SQLITE_PRIVATE void sqlite3PcacheStats(
PgHdr1 *p;
int nRecyclable = 0;
for(p=pcache1.grp.lru.pLruNext; p && !p->isAnchor; p=p->pLruNext){
- assert( p->isPinned==0 );
+ assert( PAGE_IS_UNPINNED(p) );
nRecyclable++;
}
- *pnCurrent = pcache1.grp.nCurrentPage;
+ *pnCurrent = pcache1.grp.nPurgeable;
*pnMax = (int)pcache1.grp.nMaxPage;
*pnMin = (int)pcache1.grp.nMinPage;
*pnRecyclable = nRecyclable;
@@ -46258,16 +47857,16 @@ SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, int iBatch, sqlite3_int64
/* #include "sqliteInt.h" */
-/* Additional values that can be added to the sync_flags argument of
-** sqlite3WalFrames():
+/* Macros for extracting appropriate sync flags for either transaction
+** commits (WAL_SYNC_FLAGS(X)) or for checkpoint ops (CKPT_SYNC_FLAGS(X)):
*/
-#define WAL_SYNC_TRANSACTIONS 0x20 /* Sync at the end of each transaction */
-#define SQLITE_SYNC_MASK 0x13 /* Mask off the SQLITE_SYNC_* values */
+#define WAL_SYNC_FLAGS(X) ((X)&0x03)
+#define CKPT_SYNC_FLAGS(X) (((X)>>2)&0x03)
#ifdef SQLITE_OMIT_WAL
# define sqlite3WalOpen(x,y,z) 0
# define sqlite3WalLimit(x,y)
-# define sqlite3WalClose(w,x,y,z) 0
+# define sqlite3WalClose(v,w,x,y,z) 0
# define sqlite3WalBeginReadTransaction(y,z) 0
# define sqlite3WalEndReadTransaction(z)
# define sqlite3WalDbsize(y) 0
@@ -46277,7 +47876,7 @@ SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, int iBatch, sqlite3_int64
# define sqlite3WalSavepoint(y,z)
# define sqlite3WalSavepointUndo(y,z) 0
# define sqlite3WalFrames(u,v,w,x,y,z) 0
-# define sqlite3WalCheckpoint(r,s,t,u,v,w,x,y,z) 0
+# define sqlite3WalCheckpoint(q,r,s,t,u,v,w,x,y,z) 0
# define sqlite3WalCallback(z) 0
# define sqlite3WalExclusiveMode(y,z) 0
# define sqlite3WalHeapMemory(z) 0
@@ -46295,7 +47894,7 @@ typedef struct Wal Wal;
/* Open and close a connection to a write-ahead log. */
SQLITE_PRIVATE int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *, int, i64, Wal**);
-SQLITE_PRIVATE int sqlite3WalClose(Wal *pWal, int sync_flags, int, u8 *);
+SQLITE_PRIVATE int sqlite3WalClose(Wal *pWal, sqlite3*, int sync_flags, int, u8 *);
/* Set the limiting size of a WAL file. */
SQLITE_PRIVATE void sqlite3WalLimit(Wal*, i64);
@@ -46338,6 +47937,7 @@ SQLITE_PRIVATE int sqlite3WalFrames(Wal *pWal, int, PgHdr *, Pgno, int, int);
/* Copy pages from the log to the database file */
SQLITE_PRIVATE int sqlite3WalCheckpoint(
Wal *pWal, /* Write-ahead log connection */
+ sqlite3 *db, /* Check this handle's interrupt flag */
int eMode, /* One of PASSIVE, FULL and RESTART */
int (*xBusy)(void*), /* Function to call when busy */
void *pBusyArg, /* Context argument for xBusyHandler */
@@ -46369,6 +47969,7 @@ SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal);
#ifdef SQLITE_ENABLE_SNAPSHOT
SQLITE_PRIVATE int sqlite3WalSnapshotGet(Wal *pWal, sqlite3_snapshot **ppSnapshot);
SQLITE_PRIVATE void sqlite3WalSnapshotOpen(Wal *pWal, sqlite3_snapshot *pSnapshot);
+SQLITE_PRIVATE int sqlite3WalSnapshotRecover(Wal *pWal);
#endif
#ifdef SQLITE_ENABLE_ZIPVFS
@@ -46493,8 +48094,8 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
** associated file-descriptor is returned. FILEHANDLEID() takes an sqlite3_file
** struct as its argument.
*/
-#define PAGERID(p) ((int)(p->fd))
-#define FILEHANDLEID(fd) ((int)fd)
+#define PAGERID(p) (SQLITE_PTR_TO_INT(p->fd))
+#define FILEHANDLEID(fd) (SQLITE_PTR_TO_INT(fd))
/*
** The Pager.eState variable stores the current 'state' of a pager. A
@@ -46981,6 +48582,18 @@ struct PagerSavepoint {
** is set to zero in all other states. In PAGER_ERROR state, Pager.errCode
** is always set to SQLITE_FULL, SQLITE_IOERR or one of the SQLITE_IOERR_XXX
** sub-codes.
+**
+** syncFlags, walSyncFlags
+**
+** syncFlags is either SQLITE_SYNC_NORMAL (0x02) or SQLITE_SYNC_FULL (0x03).
+** syncFlags is used for rollback mode. walSyncFlags is used for WAL mode
+** and contains the flags used to sync the checkpoint operations in the
+** lower two bits, and sync flags used for transaction commits in the WAL
+** file in bits 0x04 and 0x08. In other words, to get the correct sync flags
+** for checkpoint operations, use (walSyncFlags&0x03) and to get the correct
+** sync flags for transaction commit, use ((walSyncFlags>>2)&0x03). Note
+** that with synchronous=NORMAL in WAL mode, transaction commit is not synced
+** meaning that the 0x04 and 0x08 bits are both zero.
*/
struct Pager {
sqlite3_vfs *pVfs; /* OS functions to use for IO */
@@ -46990,9 +48603,8 @@ struct Pager {
u8 noSync; /* Do not sync the journal if true */
u8 fullSync; /* Do extra syncs of the journal for robustness */
u8 extraSync; /* sync directory after journal delete */
- u8 ckptSyncFlags; /* SYNC_NORMAL or SYNC_FULL for checkpoint */
- u8 walSyncFlags; /* SYNC_NORMAL or SYNC_FULL for wal writes */
u8 syncFlags; /* SYNC_NORMAL or SYNC_FULL otherwise */
+ u8 walSyncFlags; /* See description above */
u8 tempFile; /* zFilename is a temporary or immutable file */
u8 noLock; /* Do not lock (except in WAL mode) */
u8 readOnly; /* True for a read-only database */
@@ -47058,6 +48670,7 @@ struct Pager {
int nRead; /* Database pages read */
#endif
void (*xReiniter)(DbPage*); /* Call this routine when reloading pages */
+ int (*xGet)(Pager*,Pgno,DbPage**,int); /* Routine to fetch a patch */
#ifdef SQLITE_HAS_CODEC
void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */
void (*xCodecSizeChng)(void*,int,int); /* Notify of page size changes */
@@ -47178,14 +48791,20 @@ static const unsigned char aJournalMagic[] = {
#define isOpen(pFd) ((pFd)->pMethods!=0)
/*
-** Return true if this pager uses a write-ahead log instead of the usual
-** rollback journal. Otherwise false.
+** Return true if this pager uses a write-ahead log to read page pgno.
+** Return false if the pager reads pgno directly from the database.
*/
-#ifndef SQLITE_OMIT_WAL
-SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager){
- return (pPager->pWal!=0);
+#if !defined(SQLITE_OMIT_WAL) && defined(SQLITE_DIRECT_OVERFLOW_READ)
+SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager, Pgno pgno){
+ u32 iRead = 0;
+ int rc;
+ if( pPager->pWal==0 ) return 0;
+ rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iRead);
+ return rc || iRead;
}
-# define pagerUseWal(x) sqlite3PagerUseWal(x)
+#endif
+#ifndef SQLITE_OMIT_WAL
+# define pagerUseWal(x) ((x)->pWal!=0)
#else
# define pagerUseWal(x) 0
# define pagerRollbackWal(x) 0
@@ -47305,6 +48924,7 @@ static int assert_pager_state(Pager *p){
assert( isOpen(p->jfd)
|| p->journalMode==PAGER_JOURNALMODE_OFF
|| p->journalMode==PAGER_JOURNALMODE_WAL
+ || (sqlite3OsDeviceCharacteristics(p->fd)&SQLITE_IOCAP_BATCH_ATOMIC)
);
assert( pPager->dbOrigSize<=pPager->dbHintSize );
break;
@@ -47316,6 +48936,7 @@ static int assert_pager_state(Pager *p){
assert( isOpen(p->jfd)
|| p->journalMode==PAGER_JOURNALMODE_OFF
|| p->journalMode==PAGER_JOURNALMODE_WAL
+ || (sqlite3OsDeviceCharacteristics(p->fd)&SQLITE_IOCAP_BATCH_ATOMIC)
);
break;
@@ -47384,6 +49005,33 @@ static char *print_pager_state(Pager *p){
}
#endif
+/* Forward references to the various page getters */
+static int getPageNormal(Pager*,Pgno,DbPage**,int);
+static int getPageError(Pager*,Pgno,DbPage**,int);
+#if SQLITE_MAX_MMAP_SIZE>0
+static int getPageMMap(Pager*,Pgno,DbPage**,int);
+#endif
+
+/*
+** Set the Pager.xGet method for the appropriate routine used to fetch
+** content from the pager.
+*/
+static void setGetterMethod(Pager *pPager){
+ if( pPager->errCode ){
+ pPager->xGet = getPageError;
+#if SQLITE_MAX_MMAP_SIZE>0
+ }else if( USEFETCH(pPager)
+#ifdef SQLITE_HAS_CODEC
+ && pPager->xCodec==0
+#endif
+ ){
+ pPager->xGet = getPageMMap;
+#endif /* SQLITE_MAX_MMAP_SIZE>0 */
+ }else{
+ pPager->xGet = getPageNormal;
+ }
+}
+
/*
** Return true if it is necessary to write page *pPg into the sub-journal.
** A page needs to be written into the sub-journal if there exists one
@@ -47499,34 +49147,47 @@ static int pagerLockDb(Pager *pPager, int eLock){
}
/*
-** This function determines whether or not the atomic-write optimization
-** can be used with this pager. The optimization can be used if:
+** This function determines whether or not the atomic-write or
+** atomic-batch-write optimizations can be used with this pager. The
+** atomic-write optimization can be used if:
**
** (a) the value returned by OsDeviceCharacteristics() indicates that
** a database page may be written atomically, and
** (b) the value returned by OsSectorSize() is less than or equal
** to the page size.
**
-** The optimization is also always enabled for temporary files. It is
-** an error to call this function if pPager is opened on an in-memory
-** database.
+** If it can be used, then the value returned is the size of the journal
+** file when it contains rollback data for exactly one page.
**
-** If the optimization cannot be used, 0 is returned. If it can be used,
-** then the value returned is the size of the journal file when it
-** contains rollback data for exactly one page.
+** The atomic-batch-write optimization can be used if OsDeviceCharacteristics()
+** returns a value with the SQLITE_IOCAP_BATCH_ATOMIC bit set. -1 is
+** returned in this case.
+**
+** If neither optimization can be used, 0 is returned.
*/
-#ifdef SQLITE_ENABLE_ATOMIC_WRITE
static int jrnlBufferSize(Pager *pPager){
assert( !MEMDB );
- if( !pPager->tempFile ){
- int dc; /* Device characteristics */
- int nSector; /* Sector size */
- int szPage; /* Page size */
- assert( isOpen(pPager->fd) );
- dc = sqlite3OsDeviceCharacteristics(pPager->fd);
- nSector = pPager->sectorSize;
- szPage = pPager->pageSize;
+#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \
+ || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
+ int dc; /* Device characteristics */
+
+ assert( isOpen(pPager->fd) );
+ dc = sqlite3OsDeviceCharacteristics(pPager->fd);
+#else
+ UNUSED_PARAMETER(pPager);
+#endif
+
+#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
+ if( dc&SQLITE_IOCAP_BATCH_ATOMIC ){
+ return -1;
+ }
+#endif
+
+#ifdef SQLITE_ENABLE_ATOMIC_WRITE
+ {
+ int nSector = pPager->sectorSize;
+ int szPage = pPager->pageSize;
assert(SQLITE_IOCAP_ATOMIC512==(512>>8));
assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8));
@@ -47536,11 +49197,11 @@ static int jrnlBufferSize(Pager *pPager){
}
return JOURNAL_HDR_SZ(pPager) + JOURNAL_PG_SZ(pPager);
-}
-#else
-# define jrnlBufferSize(x) 0
#endif
+ return 0;
+}
+
/*
** If SQLITE_CHECK_PAGES is defined then we do some sanity checking
** on the cache using a hash function. This is used for testing
@@ -47622,6 +49283,7 @@ static int readMasterJournal(sqlite3_file *pJrnl, char *zMaster, u32 nMaster){
|| szJ<16
|| SQLITE_OK!=(rc = read32bits(pJrnl, szJ-16, &len))
|| len>=nMaster
+ || len>szJ-16
|| len==0
|| SQLITE_OK!=(rc = read32bits(pJrnl, szJ-12, &cksum))
|| SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8))
@@ -48198,6 +49860,7 @@ static void pager_unlock(Pager *pPager){
}
if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0);
pPager->errCode = SQLITE_OK;
+ setGetterMethod(pPager);
}
pPager->journalOff = 0;
@@ -48235,6 +49898,7 @@ static int pager_error(Pager *pPager, int rc){
if( rc2==SQLITE_FULL || rc2==SQLITE_IOERR ){
pPager->errCode = rc;
pPager->eState = PAGER_ERROR;
+ setGetterMethod(pPager);
}
return rc;
}
@@ -48341,7 +50005,9 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
}
releaseAllSavepoints(pPager);
- assert( isOpen(pPager->jfd) || pPager->pInJournal==0 );
+ assert( isOpen(pPager->jfd) || pPager->pInJournal==0
+ || (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_BATCH_ATOMIC)
+ );
if( isOpen(pPager->jfd) ){
assert( !pagerUseWal(pPager) );
@@ -48403,7 +50069,7 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
pPager->pInJournal = 0;
pPager->nRec = 0;
if( rc==SQLITE_OK ){
- if( pagerFlushOnCommit(pPager, bCommit) ){
+ if( MEMDB || pagerFlushOnCommit(pPager, bCommit) ){
sqlite3PcacheCleanAll(pPager->pPCache);
}else{
sqlite3PcacheClearWritable(pPager->pPCache);
@@ -48587,6 +50253,11 @@ static int pager_playback_one_page(
char *aData; /* Temporary storage for the page */
sqlite3_file *jfd; /* The file descriptor for the journal file */
int isSynced; /* True if journal page is synced */
+#ifdef SQLITE_HAS_CODEC
+ /* The jrnlEnc flag is true if Journal pages should be passed through
+ ** the codec. It is false for pure in-memory journals. */
+ const int jrnlEnc = (isMainJrnl || pPager->subjInMemory==0);
+#endif
assert( (isMainJrnl&~1)==0 ); /* isMainJrnl is 0 or 1 */
assert( (isSavepnt&~1)==0 ); /* isSavepnt is 0 or 1 */
@@ -48710,14 +50381,34 @@ static int pager_playback_one_page(
i64 ofst = (pgno-1)*(i64)pPager->pageSize;
testcase( !isSavepnt && pPg!=0 && (pPg->flags&PGHDR_NEED_SYNC)!=0 );
assert( !pagerUseWal(pPager) );
+
+ /* Write the data read from the journal back into the database file.
+ ** This is usually safe even for an encrypted database - as the data
+ ** was encrypted before it was written to the journal file. The exception
+ ** is if the data was just read from an in-memory sub-journal. In that
+ ** case it must be encrypted here before it is copied into the database
+ ** file. */
+#ifdef SQLITE_HAS_CODEC
+ if( !jrnlEnc ){
+ CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM_BKPT, aData);
+ rc = sqlite3OsWrite(pPager->fd, (u8 *)aData, pPager->pageSize, ofst);
+ CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM_BKPT);
+ }else
+#endif
rc = sqlite3OsWrite(pPager->fd, (u8 *)aData, pPager->pageSize, ofst);
+
if( pgno>pPager->dbFileSize ){
pPager->dbFileSize = pgno;
}
if( pPager->pBackup ){
- CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM_BKPT);
+#ifdef SQLITE_HAS_CODEC
+ if( jrnlEnc ){
+ CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM_BKPT);
+ sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)aData);
+ CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM_BKPT,aData);
+ }else
+#endif
sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)aData);
- CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM_BKPT, aData);
}
}else if( !isMainJrnl && pPg==0 ){
/* If this is a rollback of a savepoint and data was not written to
@@ -48769,7 +50460,9 @@ static int pager_playback_one_page(
}
/* Decode the page just read from disk */
- CODEC1(pPager, pData, pPg->pgno, 3, rc=SQLITE_NOMEM_BKPT);
+#if SQLITE_HAS_CODEC
+ if( jrnlEnc ){ CODEC1(pPager, pData, pPg->pgno, 3, rc=SQLITE_NOMEM_BKPT); }
+#endif
sqlite3PcacheRelease(pPg);
}
return rc;
@@ -49082,6 +50775,7 @@ static int pager_playback(Pager *pPager, int isHot){
char *zMaster = 0; /* Name of master journal file if any */
int needPagerReset; /* True to reset page prior to first page rollback */
int nPlayback = 0; /* Total number of pages restored from journal */
+ u32 savedPageSize = pPager->pageSize;
/* Figure out how many records are in the journal. Abort early if
** the journal is empty.
@@ -49211,6 +50905,9 @@ static int pager_playback(Pager *pPager, int isHot){
assert( 0 );
end_playback:
+ if( rc==SQLITE_OK ){
+ rc = sqlite3PagerSetPagesize(pPager, &savedPageSize, -1);
+ }
/* Following a rollback, the database file should be back in its original
** state prior to the start of the transaction, so invoke the
** SQLITE_FCNTL_DB_UNCHANGED file-control method to disable the
@@ -49269,7 +50966,8 @@ static int pager_playback(Pager *pPager, int isHot){
/*
-** Read the content for page pPg out of the database file and into
+** Read the content for page pPg out of the database file (or out of
+** the WAL if that is where the most recent copy if found) into
** pPg->pData. A shared lock or greater must be held on the database
** file before this function is called.
**
@@ -49279,30 +50977,33 @@ static int pager_playback(Pager *pPager, int isHot){
** If an IO error occurs, then the IO error is returned to the caller.
** Otherwise, SQLITE_OK is returned.
*/
-static int readDbPage(PgHdr *pPg, u32 iFrame){
+static int readDbPage(PgHdr *pPg){
Pager *pPager = pPg->pPager; /* Pager object associated with page pPg */
- Pgno pgno = pPg->pgno; /* Page number to read */
int rc = SQLITE_OK; /* Return code */
- int pgsz = pPager->pageSize; /* Number of bytes to read */
+
+#ifndef SQLITE_OMIT_WAL
+ u32 iFrame = 0; /* Frame of WAL containing pgno */
assert( pPager->eState>=PAGER_READER && !MEMDB );
assert( isOpen(pPager->fd) );
-#ifndef SQLITE_OMIT_WAL
+ if( pagerUseWal(pPager) ){
+ rc = sqlite3WalFindFrame(pPager->pWal, pPg->pgno, &iFrame);
+ if( rc ) return rc;
+ }
if( iFrame ){
- /* Try to pull the page from the write-ahead log. */
- rc = sqlite3WalReadFrame(pPager->pWal, iFrame, pgsz, pPg->pData);
+ rc = sqlite3WalReadFrame(pPager->pWal, iFrame,pPager->pageSize,pPg->pData);
}else
#endif
{
- i64 iOffset = (pgno-1)*(i64)pPager->pageSize;
- rc = sqlite3OsRead(pPager->fd, pPg->pData, pgsz, iOffset);
+ i64 iOffset = (pPg->pgno-1)*(i64)pPager->pageSize;
+ rc = sqlite3OsRead(pPager->fd, pPg->pData, pPager->pageSize, iOffset);
if( rc==SQLITE_IOERR_SHORT_READ ){
rc = SQLITE_OK;
}
}
- if( pgno==1 ){
+ if( pPg->pgno==1 ){
if( rc ){
/* If the read is unsuccessful, set the dbFileVers[] to something
** that will never be a valid file version. dbFileVers[] is a copy
@@ -49322,13 +51023,13 @@ static int readDbPage(PgHdr *pPg, u32 iFrame){
memcpy(&pPager->dbFileVers, dbFileVers, sizeof(pPager->dbFileVers));
}
}
- CODEC1(pPager, pPg->pData, pgno, 3, rc = SQLITE_NOMEM_BKPT);
+ CODEC1(pPager, pPg->pData, pPg->pgno, 3, rc = SQLITE_NOMEM_BKPT);
PAGER_INCR(sqlite3_pager_readdb_count);
PAGER_INCR(pPager->nRead);
- IOTRACE(("PGIN %p %d\n", pPager, pgno));
+ IOTRACE(("PGIN %p %d\n", pPager, pPg->pgno));
PAGERTRACE(("FETCH %d page %d hash(%08x)\n",
- PAGERID(pPager), pgno, pager_pagehash(pPg)));
+ PAGERID(pPager), pPg->pgno, pager_pagehash(pPg)));
return rc;
}
@@ -49379,11 +51080,7 @@ static int pagerUndoCallback(void *pCtx, Pgno iPg){
if( sqlite3PcachePageRefcount(pPg)==1 ){
sqlite3PcacheDrop(pPg);
}else{
- u32 iFrame = 0;
- rc = sqlite3WalFindFrame(pPager->pWal, pPg->pgno, &iFrame);
- if( rc==SQLITE_OK ){
- rc = readDbPage(pPg, iFrame);
- }
+ rc = readDbPage(pPg);
if( rc==SQLITE_OK ){
pPager->xReiniter(pPg);
}
@@ -49555,7 +51252,7 @@ static int pagerPagecount(Pager *pPager, Pgno *pnPage){
nPage = sqlite3WalDbsize(pPager->pWal);
/* If the number of pages in the database is not available from the
- ** WAL sub-system, determine the page counte based on the size of
+ ** WAL sub-system, determine the page count based on the size of
** the database file. If the size of the database file is not an
** integer multiple of the page-size, round up the result.
*/
@@ -49606,23 +51303,21 @@ static int pagerOpenWalIfPresent(Pager *pPager){
if( !pPager->tempFile ){
int isWal; /* True if WAL file exists */
- Pgno nPage; /* Size of the database file */
-
- rc = pagerPagecount(pPager, &nPage);
- if( rc ) return rc;
- if( nPage==0 ){
- rc = sqlite3OsDelete(pPager->pVfs, pPager->zWal, 0);
- if( rc==SQLITE_IOERR_DELETE_NOENT ) rc = SQLITE_OK;
- isWal = 0;
- }else{
- rc = sqlite3OsAccess(
- pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &isWal
- );
- }
+ rc = sqlite3OsAccess(
+ pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &isWal
+ );
if( rc==SQLITE_OK ){
if( isWal ){
- testcase( sqlite3PcachePagecount(pPager->pPCache)==0 );
- rc = sqlite3PagerOpenWal(pPager, 0);
+ Pgno nPage; /* Size of the database file */
+
+ rc = pagerPagecount(pPager, &nPage);
+ if( rc ) return rc;
+ if( nPage==0 ){
+ rc = sqlite3OsDelete(pPager->pVfs, pPager->zWal, 0);
+ }else{
+ testcase( sqlite3PcachePagecount(pPager->pPCache)==0 );
+ rc = sqlite3PagerOpenWal(pPager, 0);
+ }
}else if( pPager->journalMode==PAGER_JOURNALMODE_WAL ){
pPager->journalMode = PAGER_JOURNALMODE_DELETE;
}
@@ -49802,6 +51497,7 @@ static void pagerFixMaplimit(Pager *pPager){
sqlite3_int64 sz;
sz = pPager->szMmap;
pPager->bUseFetch = (sz>0);
+ setGetterMethod(pPager);
sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_MMAP_SIZE, &sz);
}
#endif
@@ -49890,20 +51586,17 @@ SQLITE_PRIVATE void sqlite3PagerSetFlags(
}
if( pPager->noSync ){
pPager->syncFlags = 0;
- pPager->ckptSyncFlags = 0;
}else if( pgFlags & PAGER_FULLFSYNC ){
pPager->syncFlags = SQLITE_SYNC_FULL;
- pPager->ckptSyncFlags = SQLITE_SYNC_FULL;
- }else if( pgFlags & PAGER_CKPT_FULLFSYNC ){
- pPager->syncFlags = SQLITE_SYNC_NORMAL;
- pPager->ckptSyncFlags = SQLITE_SYNC_FULL;
}else{
pPager->syncFlags = SQLITE_SYNC_NORMAL;
- pPager->ckptSyncFlags = SQLITE_SYNC_NORMAL;
}
- pPager->walSyncFlags = pPager->syncFlags;
+ pPager->walSyncFlags = (pPager->syncFlags<<2);
if( pPager->fullSync ){
- pPager->walSyncFlags |= WAL_SYNC_TRANSACTIONS;
+ pPager->walSyncFlags |= pPager->syncFlags;
+ }
+ if( (pgFlags & PAGER_CKPT_FULLFSYNC) && !pPager->noSync ){
+ pPager->walSyncFlags |= (SQLITE_SYNC_FULL<<2);
}
if( pgFlags & PAGER_CACHESPILL ){
pPager->doNotSpill &= ~SPILLFLAG_OFF;
@@ -50298,6 +51991,7 @@ static int pagerSyncHotJournal(Pager *pPager){
return rc;
}
+#if SQLITE_MAX_MMAP_SIZE>0
/*
** Obtain a reference to a memory mapped page object for page number pgno.
** The new object will use the pointer pData, obtained from xFetch().
@@ -50320,7 +52014,8 @@ static int pagerAcquireMapPage(
*ppPage = p = pPager->pMmapFreelist;
pPager->pMmapFreelist = p->pDirty;
p->pDirty = 0;
- memset(p->pExtra, 0, pPager->nExtra);
+ assert( pPager->nExtra>=8 );
+ memset(p->pExtra, 0, 8);
}else{
*ppPage = p = (PgHdr *)sqlite3MallocZero(sizeof(PgHdr) + pPager->nExtra);
if( p==0 ){
@@ -50345,6 +52040,7 @@ static int pagerAcquireMapPage(
return SQLITE_OK;
}
+#endif
/*
** Release a reference to page pPg. pPg must have been returned by an
@@ -50387,9 +52083,10 @@ static void pagerFreeMapHdrs(Pager *pPager){
** a hot journal may be left in the filesystem but no error is returned
** to the caller.
*/
-SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){
+SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3 *db){
u8 *pTmp = (u8 *)pPager->pTmpSpace;
+ assert( db || pagerUseWal(pPager)==0 );
assert( assert_pager_state(pPager) );
disable_simulated_io_errors();
sqlite3BeginBenignMalloc();
@@ -50397,7 +52094,10 @@ SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){
/* pPager->errCode = 0; */
pPager->exclusiveMode = 0;
#ifndef SQLITE_OMIT_WAL
- sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags, pPager->pageSize, pTmp);
+ assert( db || pPager->pWal==0 );
+ sqlite3WalClose(pPager->pWal, db, pPager->walSyncFlags, pPager->pageSize,
+ (db && (db->flags & SQLITE_NoCkptOnClose) ? 0 : pTmp)
+ );
pPager->pWal = 0;
#endif
pager_reset(pPager);
@@ -50773,8 +52473,13 @@ static int subjournalPage(PgHdr *pPg){
void *pData = pPg->pData;
i64 offset = (i64)pPager->nSubRec*(4+pPager->pageSize);
char *pData2;
-
- CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM_BKPT, pData2);
+
+#if SQLITE_HAS_CODEC
+ if( !pPager->subjInMemory ){
+ CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM_BKPT, pData2);
+ }else
+#endif
+ pData2 = pData;
PAGERTRACE(("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno));
rc = write32bits(pPager->sjfd, offset, pPg->pgno);
if( rc==SQLITE_OK ){
@@ -50858,6 +52563,13 @@ static int pagerStress(void *p, PgHdr *pPg){
rc = pagerWalFrames(pPager, pPg, 0, 0);
}
}else{
+
+#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
+ if( pPager->tempFile==0 ){
+ rc = sqlite3JournalCreate(pPager->jfd);
+ if( rc!=SQLITE_OK ) return pager_error(pPager, rc);
+ }
+#endif
/* Sync the journal file if required. */
if( pPg->flags&PGHDR_NEED_SYNC
@@ -50916,7 +52628,9 @@ SQLITE_PRIVATE int sqlite3PagerFlush(Pager *pPager){
**
** The nExtra parameter specifies the number of bytes of space allocated
** along with each page reference. This space is available to the user
-** via the sqlite3PagerGetExtra() API.
+** via the sqlite3PagerGetExtra() API. When a new page is allocated, the
+** first 8 bytes of this space are zeroed but the remainder is uninitialized.
+** (The extra space is used by btree as the MemPage object.)
**
** The flags argument is used to specify properties that affect the
** operation of the pager. It should be passed some bitwise combination
@@ -51146,8 +52860,8 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
/* Initialize the PCache object. */
if( rc==SQLITE_OK ){
- assert( nExtra<1000 );
nExtra = ROUND8(nExtra);
+ assert( nExtra>=8 && nExtra<1000 );
rc = sqlite3PcacheOpen(szPageDflt, nExtra, !memDb,
!memDb?pagerStress:0, (void *)pPager, pPager->pPCache);
}
@@ -51189,13 +52903,11 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
assert( pPager->extraSync==0 );
assert( pPager->syncFlags==0 );
assert( pPager->walSyncFlags==0 );
- assert( pPager->ckptSyncFlags==0 );
}else{
pPager->fullSync = 1;
pPager->extraSync = 0;
pPager->syncFlags = SQLITE_SYNC_NORMAL;
- pPager->walSyncFlags = SQLITE_SYNC_NORMAL | WAL_SYNC_TRANSACTIONS;
- pPager->ckptSyncFlags = SQLITE_SYNC_NORMAL;
+ pPager->walSyncFlags = SQLITE_SYNC_NORMAL | (SQLITE_SYNC_NORMAL<<2);
}
/* pPager->pFirst = 0; */
/* pPager->pFirstSynced = 0; */
@@ -51212,6 +52924,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
/* pPager->xBusyHandler = 0; */
/* pPager->pBusyHandlerArg = 0; */
pPager->xReiniter = xReinit;
+ setGetterMethod(pPager);
/* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */
/* pPager->szMmap = SQLITE_DEFAULT_MMAP_SIZE // will be set by btree.c */
@@ -51549,19 +53262,14 @@ SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){
** detected. The chance of an undetected change is so small that
** it can be neglected.
*/
- Pgno nPage = 0;
char dbFileVers[sizeof(pPager->dbFileVers)];
- rc = pagerPagecount(pPager, &nPage);
- if( rc ) goto failed;
-
- if( nPage>0 ){
- IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers)));
- rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers), 24);
- if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){
+ IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers)));
+ rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers), 24);
+ if( rc!=SQLITE_OK ){
+ if( rc!=SQLITE_IOERR_SHORT_READ ){
goto failed;
}
- }else{
memset(dbFileVers, 0, sizeof(dbFileVers));
}
@@ -51619,16 +53327,24 @@ SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){
** nothing to rollback, so this routine is a no-op.
*/
static void pagerUnlockIfUnused(Pager *pPager){
- if( pPager->nMmapOut==0 && (sqlite3PcacheRefCount(pPager->pPCache)==0) ){
+ if( sqlite3PcacheRefCount(pPager->pPCache)==0 ){
+ assert( pPager->nMmapOut==0 ); /* because page1 is never memory mapped */
pagerUnlockAndRollback(pPager);
}
}
/*
-** Acquire a reference to page number pgno in pager pPager (a page
-** reference has type DbPage*). If the requested reference is
+** The page getter methods each try to acquire a reference to a
+** page with page number pgno. If the requested reference is
** successfully obtained, it is copied to *ppPage and SQLITE_OK returned.
**
+** There are different implementations of the getter method depending
+** on the current state of the pager.
+**
+** getPageNormal() -- The normal getter
+** getPageError() -- Used if the pager is in an error state
+** getPageMmap() -- Used if memory-mapped I/O is enabled
+**
** If the requested page is already in the cache, it is returned.
** Otherwise, a new page object is allocated and populated with data
** read from the database file. In some cases, the pcache module may
@@ -51640,14 +53356,14 @@ static void pagerUnlockIfUnused(Pager *pPager){
** already in the cache when this function is called, then the extra
** data is left as it was when the page object was last used.
**
-** If the database image is smaller than the requested page or if a
-** non-zero value is passed as the noContent parameter and the
+** If the database image is smaller than the requested page or if
+** the flags parameter contains the PAGER_GET_NOCONTENT bit and the
** requested page is not already stored in the cache, then no
** actual disk read occurs. In this case the memory image of the
** page is initialized to all zeros.
**
-** If noContent is true, it means that we do not care about the contents
-** of the page. This occurs in two scenarios:
+** If PAGER_GET_NOCONTENT is true, it means that we do not care about
+** the contents of the page. This occurs in two scenarios:
**
** a) When reading a free-list leaf page from the database, and
**
@@ -51655,8 +53371,8 @@ static void pagerUnlockIfUnused(Pager *pPager){
** a new page into the cache to be filled with the data read
** from the savepoint journal.
**
-** If noContent is true, then the data returned is zeroed instead of
-** being read from the database. Additionally, the bits corresponding
+** If PAGER_GET_NOCONTENT is true, then the data returned is zeroed instead
+** of being read from the database. Additionally, the bits corresponding
** to pgno in Pager.pInJournal (bitvec of pages already written to the
** journal file) and the PagerSavepoint.pInSavepoint bitvecs of any open
** savepoints are set. This means if the page is made writable at any
@@ -51674,106 +53390,39 @@ static void pagerUnlockIfUnused(Pager *pPager){
** Since Lookup() never goes to disk, it never has to deal with locks
** or journal files.
*/
-SQLITE_PRIVATE int sqlite3PagerGet(
+static int getPageNormal(
Pager *pPager, /* The pager open on the database file */
Pgno pgno, /* Page number to fetch */
DbPage **ppPage, /* Write a pointer to the page here */
int flags /* PAGER_GET_XXX flags */
){
int rc = SQLITE_OK;
- PgHdr *pPg = 0;
- u32 iFrame = 0; /* Frame to read from WAL file */
- const int noContent = (flags & PAGER_GET_NOCONTENT);
-
- /* It is acceptable to use a read-only (mmap) page for any page except
- ** page 1 if there is no write-transaction open or the ACQUIRE_READONLY
- ** flag was specified by the caller. And so long as the db is not a
- ** temporary or in-memory database. */
- const int bMmapOk = (pgno>1 && USEFETCH(pPager)
- && (pPager->eState==PAGER_READER || (flags & PAGER_GET_READONLY))
-#ifdef SQLITE_HAS_CODEC
- && pPager->xCodec==0
-#endif
- );
+ PgHdr *pPg;
+ u8 noContent; /* True if PAGER_GET_NOCONTENT is set */
+ sqlite3_pcache_page *pBase;
- /* Optimization note: Adding the "pgno<=1" term before "pgno==0" here
- ** allows the compiler optimizer to reuse the results of the "pgno>1"
- ** test in the previous statement, and avoid testing pgno==0 in the
- ** common case where pgno is large. */
- if( pgno<=1 && pgno==0 ){
- return SQLITE_CORRUPT_BKPT;
- }
+ assert( pPager->errCode==SQLITE_OK );
assert( pPager->eState>=PAGER_READER );
assert( assert_pager_state(pPager) );
- assert( noContent==0 || bMmapOk==0 );
-
assert( pPager->hasHeldSharedLock==1 );
- /* If the pager is in the error state, return an error immediately.
- ** Otherwise, request the page from the PCache layer. */
- if( pPager->errCode!=SQLITE_OK ){
- rc = pPager->errCode;
- }else{
- if( bMmapOk && pagerUseWal(pPager) ){
- rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame);
- if( rc!=SQLITE_OK ) goto pager_acquire_err;
- }
-
- if( bMmapOk && iFrame==0 ){
- void *pData = 0;
-
- rc = sqlite3OsFetch(pPager->fd,
- (i64)(pgno-1) * pPager->pageSize, pPager->pageSize, &pData
- );
-
- if( rc==SQLITE_OK && pData ){
- if( pPager->eState>PAGER_READER || pPager->tempFile ){
- pPg = sqlite3PagerLookup(pPager, pgno);
- }
- if( pPg==0 ){
- rc = pagerAcquireMapPage(pPager, pgno, pData, &pPg);
- }else{
- sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1)*pPager->pageSize, pData);
- }
- if( pPg ){
- assert( rc==SQLITE_OK );
- *ppPage = pPg;
- return SQLITE_OK;
- }
- }
- if( rc!=SQLITE_OK ){
- goto pager_acquire_err;
- }
- }
-
- {
- sqlite3_pcache_page *pBase;
- pBase = sqlite3PcacheFetch(pPager->pPCache, pgno, 3);
- if( pBase==0 ){
- rc = sqlite3PcacheFetchStress(pPager->pPCache, pgno, &pBase);
- if( rc!=SQLITE_OK ) goto pager_acquire_err;
- if( pBase==0 ){
- pPg = *ppPage = 0;
- rc = SQLITE_NOMEM_BKPT;
- goto pager_acquire_err;
- }
- }
- pPg = *ppPage = sqlite3PcacheFetchFinish(pPager->pPCache, pgno, pBase);
- assert( pPg!=0 );
- }
- }
-
- if( rc!=SQLITE_OK ){
- /* Either the call to sqlite3PcacheFetch() returned an error or the
- ** pager was already in the error-state when this function was called.
- ** Set pPg to 0 and jump to the exception handler. */
+ if( pgno==0 ) return SQLITE_CORRUPT_BKPT;
+ pBase = sqlite3PcacheFetch(pPager->pPCache, pgno, 3);
+ if( pBase==0 ){
pPg = 0;
- goto pager_acquire_err;
+ rc = sqlite3PcacheFetchStress(pPager->pPCache, pgno, &pBase);
+ if( rc!=SQLITE_OK ) goto pager_acquire_err;
+ if( pBase==0 ){
+ rc = SQLITE_NOMEM_BKPT;
+ goto pager_acquire_err;
+ }
}
+ pPg = *ppPage = sqlite3PcacheFetchFinish(pPager->pPCache, pgno, pBase);
assert( pPg==(*ppPage) );
assert( pPg->pgno==pgno );
assert( pPg->pPager==pPager || pPg->pPager==0 );
+ noContent = (flags & PAGER_GET_NOCONTENT)!=0;
if( pPg->pPager && !noContent ){
/* In this case the pcache already contains an initialized copy of
** the page. Return without further ado. */
@@ -51783,17 +53432,18 @@ SQLITE_PRIVATE int sqlite3PagerGet(
}else{
/* The pager cache has created a new page. Its content needs to
- ** be initialized. */
-
- pPg->pPager = pPager;
-
- /* The maximum page number is 2^31. Return SQLITE_CORRUPT if a page
- ** number greater than this, or the unused locking-page, is requested. */
+ ** be initialized. But first some error checks:
+ **
+ ** (1) The maximum page number is 2^31
+ ** (2) Never try to fetch the locking page
+ */
if( pgno>PAGER_MAX_PGNO || pgno==PAGER_MJ_PGNO(pPager) ){
rc = SQLITE_CORRUPT_BKPT;
goto pager_acquire_err;
}
+ pPg->pPager = pPager;
+
assert( !isOpen(pPager->fd) || !MEMDB );
if( !isOpen(pPager->fd) || pPager->dbSizepPager->mxPgno ){
@@ -51819,20 +53469,15 @@ SQLITE_PRIVATE int sqlite3PagerGet(
memset(pPg->pData, 0, pPager->pageSize);
IOTRACE(("ZERO %p %d\n", pPager, pgno));
}else{
- if( pagerUseWal(pPager) && bMmapOk==0 ){
- rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame);
- if( rc!=SQLITE_OK ) goto pager_acquire_err;
- }
assert( pPg->pPager==pPager );
pPager->aStat[PAGER_STAT_MISS]++;
- rc = readDbPage(pPg, iFrame);
+ rc = readDbPage(pPg);
if( rc!=SQLITE_OK ){
goto pager_acquire_err;
}
}
pager_set_pagehash(pPg);
}
-
return SQLITE_OK;
pager_acquire_err:
@@ -51841,11 +53486,109 @@ SQLITE_PRIVATE int sqlite3PagerGet(
sqlite3PcacheDrop(pPg);
}
pagerUnlockIfUnused(pPager);
-
*ppPage = 0;
return rc;
}
+#if SQLITE_MAX_MMAP_SIZE>0
+/* The page getter for when memory-mapped I/O is enabled */
+static int getPageMMap(
+ Pager *pPager, /* The pager open on the database file */
+ Pgno pgno, /* Page number to fetch */
+ DbPage **ppPage, /* Write a pointer to the page here */
+ int flags /* PAGER_GET_XXX flags */
+){
+ int rc = SQLITE_OK;
+ PgHdr *pPg = 0;
+ u32 iFrame = 0; /* Frame to read from WAL file */
+
+ /* It is acceptable to use a read-only (mmap) page for any page except
+ ** page 1 if there is no write-transaction open or the ACQUIRE_READONLY
+ ** flag was specified by the caller. And so long as the db is not a
+ ** temporary or in-memory database. */
+ const int bMmapOk = (pgno>1
+ && (pPager->eState==PAGER_READER || (flags & PAGER_GET_READONLY))
+ );
+
+ assert( USEFETCH(pPager) );
+#ifdef SQLITE_HAS_CODEC
+ assert( pPager->xCodec==0 );
+#endif
+
+ /* Optimization note: Adding the "pgno<=1" term before "pgno==0" here
+ ** allows the compiler optimizer to reuse the results of the "pgno>1"
+ ** test in the previous statement, and avoid testing pgno==0 in the
+ ** common case where pgno is large. */
+ if( pgno<=1 && pgno==0 ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+ assert( pPager->eState>=PAGER_READER );
+ assert( assert_pager_state(pPager) );
+ assert( pPager->hasHeldSharedLock==1 );
+ assert( pPager->errCode==SQLITE_OK );
+
+ if( bMmapOk && pagerUseWal(pPager) ){
+ rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame);
+ if( rc!=SQLITE_OK ){
+ *ppPage = 0;
+ return rc;
+ }
+ }
+ if( bMmapOk && iFrame==0 ){
+ void *pData = 0;
+ rc = sqlite3OsFetch(pPager->fd,
+ (i64)(pgno-1) * pPager->pageSize, pPager->pageSize, &pData
+ );
+ if( rc==SQLITE_OK && pData ){
+ if( pPager->eState>PAGER_READER || pPager->tempFile ){
+ pPg = sqlite3PagerLookup(pPager, pgno);
+ }
+ if( pPg==0 ){
+ rc = pagerAcquireMapPage(pPager, pgno, pData, &pPg);
+ }else{
+ sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1)*pPager->pageSize, pData);
+ }
+ if( pPg ){
+ assert( rc==SQLITE_OK );
+ *ppPage = pPg;
+ return SQLITE_OK;
+ }
+ }
+ if( rc!=SQLITE_OK ){
+ *ppPage = 0;
+ return rc;
+ }
+ }
+ return getPageNormal(pPager, pgno, ppPage, flags);
+}
+#endif /* SQLITE_MAX_MMAP_SIZE>0 */
+
+/* The page getter method for when the pager is an error state */
+static int getPageError(
+ Pager *pPager, /* The pager open on the database file */
+ Pgno pgno, /* Page number to fetch */
+ DbPage **ppPage, /* Write a pointer to the page here */
+ int flags /* PAGER_GET_XXX flags */
+){
+ UNUSED_PARAMETER(pgno);
+ UNUSED_PARAMETER(flags);
+ assert( pPager->errCode!=SQLITE_OK );
+ *ppPage = 0;
+ return pPager->errCode;
+}
+
+
+/* Dispatch all page fetch requests to the appropriate getter method.
+*/
+SQLITE_PRIVATE int sqlite3PagerGet(
+ Pager *pPager, /* The pager open on the database file */
+ Pgno pgno, /* Page number to fetch */
+ DbPage **ppPage, /* Write a pointer to the page here */
+ int flags /* PAGER_GET_XXX flags */
+){
+ return pPager->xGet(pPager, pgno, ppPage, flags);
+}
+
/*
** Acquire a page if it is already in the in-memory cache. Do
** not read the page from disk. Return a pointer to the page,
@@ -51871,25 +53614,39 @@ SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){
/*
** Release a page reference.
**
-** If the number of references to the page drop to zero, then the
-** page is added to the LRU list. When all references to all pages
-** are released, a rollback occurs and the lock on the database is
-** removed.
+** The sqlite3PagerUnref() and sqlite3PagerUnrefNotNull() may only be
+** used if we know that the page being released is not the last page.
+** The btree layer always holds page1 open until the end, so these first
+** to routines can be used to release any page other than BtShared.pPage1.
+**
+** Use sqlite3PagerUnrefPageOne() to release page1. This latter routine
+** checks the total number of outstanding pages and if the number of
+** pages reaches zero it drops the database lock.
*/
SQLITE_PRIVATE void sqlite3PagerUnrefNotNull(DbPage *pPg){
- Pager *pPager;
+ TESTONLY( Pager *pPager = pPg->pPager; )
assert( pPg!=0 );
- pPager = pPg->pPager;
if( pPg->flags & PGHDR_MMAP ){
+ assert( pPg->pgno!=1 ); /* Page1 is never memory mapped */
pagerReleaseMapPage(pPg);
}else{
sqlite3PcacheRelease(pPg);
}
- pagerUnlockIfUnused(pPager);
+ /* Do not use this routine to release the last reference to page1 */
+ assert( sqlite3PcacheRefCount(pPager->pPCache)>0 );
}
SQLITE_PRIVATE void sqlite3PagerUnref(DbPage *pPg){
if( pPg ) sqlite3PagerUnrefNotNull(pPg);
}
+SQLITE_PRIVATE void sqlite3PagerUnrefPageOne(DbPage *pPg){
+ Pager *pPager;
+ assert( pPg!=0 );
+ assert( pPg->pgno==1 );
+ assert( (pPg->flags & PGHDR_MMAP)==0 ); /* Page1 is never memory mapped */
+ pPager = pPg->pPager;
+ sqlite3PcacheRelease(pPg);
+ pagerUnlockIfUnused(pPager);
+}
/*
** This function is called at the start of every write transaction.
@@ -52319,11 +54076,11 @@ SQLITE_PRIVATE int sqlite3PagerWrite(PgHdr *pPg){
assert( (pPg->flags & PGHDR_MMAP)==0 );
assert( pPager->eState>=PAGER_WRITER_LOCKED );
assert( assert_pager_state(pPager) );
- if( pPager->errCode ){
- return pPager->errCode;
- }else if( (pPg->flags & PGHDR_WRITEABLE)!=0 && pPager->dbSize>=pPg->pgno ){
+ if( (pPg->flags & PGHDR_WRITEABLE)!=0 && pPager->dbSize>=pPg->pgno ){
if( pPager->nSavepoint ) return subjournalPageIfRequired(pPg);
return SQLITE_OK;
+ }else if( pPager->errCode ){
+ return pPager->errCode;
}else if( pPager->sectorSize > (u32)pPager->pageSize ){
assert( pPager->tempFile==0 );
return pagerWriteLargeSector(pPg);
@@ -52601,6 +54358,21 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
sqlite3PcacheCleanAll(pPager->pPCache);
}
}else{
+ /* The bBatch boolean is true if the batch-atomic-write commit method
+ ** should be used. No rollback journal is created if batch-atomic-write
+ ** is enabled.
+ */
+ sqlite3_file *fd = pPager->fd;
+#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
+ const int bBatch = zMaster==0 /* An SQLITE_IOCAP_BATCH_ATOMIC commit */
+ && (sqlite3OsDeviceCharacteristics(fd) & SQLITE_IOCAP_BATCH_ATOMIC)
+ && !pPager->noSync
+ && sqlite3JournalIsInMemory(pPager->jfd);
+#else
+# define bBatch 0
+#endif
+
+#ifdef SQLITE_ENABLE_ATOMIC_WRITE
/* The following block updates the change-counter. Exactly how it
** does this depends on whether or not the atomic-update optimization
** was enabled at compile time, and if this transaction meets the
@@ -52624,33 +54396,40 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
** in 'direct' mode. In this case the journal file will never be
** created for this transaction.
*/
- #ifdef SQLITE_ENABLE_ATOMIC_WRITE
- PgHdr *pPg;
- assert( isOpen(pPager->jfd)
- || pPager->journalMode==PAGER_JOURNALMODE_OFF
- || pPager->journalMode==PAGER_JOURNALMODE_WAL
- );
- if( !zMaster && isOpen(pPager->jfd)
- && pPager->journalOff==jrnlBufferSize(pPager)
- && pPager->dbSize>=pPager->dbOrigSize
- && (0==(pPg = sqlite3PcacheDirtyList(pPager->pPCache)) || 0==pPg->pDirty)
- ){
- /* Update the db file change counter via the direct-write method. The
- ** following call will modify the in-memory representation of page 1
- ** to include the updated change counter and then write page 1
- ** directly to the database file. Because of the atomic-write
- ** property of the host file-system, this is safe.
- */
- rc = pager_incr_changecounter(pPager, 1);
- }else{
- rc = sqlite3JournalCreate(pPager->jfd);
- if( rc==SQLITE_OK ){
- rc = pager_incr_changecounter(pPager, 0);
+ if( bBatch==0 ){
+ PgHdr *pPg;
+ assert( isOpen(pPager->jfd)
+ || pPager->journalMode==PAGER_JOURNALMODE_OFF
+ || pPager->journalMode==PAGER_JOURNALMODE_WAL
+ );
+ if( !zMaster && isOpen(pPager->jfd)
+ && pPager->journalOff==jrnlBufferSize(pPager)
+ && pPager->dbSize>=pPager->dbOrigSize
+ && (!(pPg = sqlite3PcacheDirtyList(pPager->pPCache)) || 0==pPg->pDirty)
+ ){
+ /* Update the db file change counter via the direct-write method. The
+ ** following call will modify the in-memory representation of page 1
+ ** to include the updated change counter and then write page 1
+ ** directly to the database file. Because of the atomic-write
+ ** property of the host file-system, this is safe.
+ */
+ rc = pager_incr_changecounter(pPager, 1);
+ }else{
+ rc = sqlite3JournalCreate(pPager->jfd);
+ if( rc==SQLITE_OK ){
+ rc = pager_incr_changecounter(pPager, 0);
+ }
}
}
- #else
+#else
+#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
+ if( zMaster ){
+ rc = sqlite3JournalCreate(pPager->jfd);
+ if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
+ }
+#endif
rc = pager_incr_changecounter(pPager, 0);
- #endif
+#endif
if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
/* Write the master journal name into the journal file. If a master
@@ -52673,8 +54452,24 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
*/
rc = syncJournal(pPager, 0);
if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
-
+
+ if( bBatch ){
+ /* The pager is now in DBMOD state. But regardless of what happens
+ ** next, attempting to play the journal back into the database would
+ ** be unsafe. Close it now to make sure that does not happen. */
+ sqlite3OsClose(pPager->jfd);
+ rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_BEGIN_ATOMIC_WRITE, 0);
+ if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
+ }
rc = pager_write_pagelist(pPager,sqlite3PcacheDirtyList(pPager->pPCache));
+ if( bBatch ){
+ if( rc==SQLITE_OK ){
+ rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_COMMIT_ATOMIC_WRITE, 0);
+ }else{
+ sqlite3OsFileControl(fd, SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE, 0);
+ }
+ }
+
if( rc!=SQLITE_OK ){
assert( rc!=SQLITE_IOERR_BLOCKED );
goto commit_phase_one_exit;
@@ -52818,6 +54613,7 @@ SQLITE_PRIVATE int sqlite3PagerRollback(Pager *pPager){
*/
pPager->errCode = SQLITE_ABORT;
pPager->eState = PAGER_ERROR;
+ setGetterMethod(pPager);
return rc;
}
}else{
@@ -53079,6 +54875,7 @@ SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){
){
pPager->errCode = SQLITE_ABORT;
pPager->eState = PAGER_ERROR;
+ setGetterMethod(pPager);
}
#endif
}
@@ -53151,6 +54948,7 @@ SQLITE_PRIVATE void sqlite3PagerSetCodec(
pPager->xCodecSizeChng = xCodecSizeChng;
pPager->xCodecFree = xCodecFree;
pPager->pCodec = pCodec;
+ setGetterMethod(pPager);
pagerReportSize(pPager);
}
SQLITE_PRIVATE void *sqlite3PagerGetCodec(Pager *pPager){
@@ -53560,13 +55358,19 @@ SQLITE_PRIVATE void sqlite3PagerClearCache(Pager *pPager){
**
** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART.
*/
-SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int eMode, int *pnLog, int *pnCkpt){
+SQLITE_PRIVATE int sqlite3PagerCheckpoint(
+ Pager *pPager, /* Checkpoint on this pager */
+ sqlite3 *db, /* Db handle used to check for interrupts */
+ int eMode, /* Type of checkpoint */
+ int *pnLog, /* OUT: Final number of frames in log */
+ int *pnCkpt /* OUT: Final number of checkpointed frames */
+){
int rc = SQLITE_OK;
if( pPager->pWal ){
- rc = sqlite3WalCheckpoint(pPager->pWal, eMode,
+ rc = sqlite3WalCheckpoint(pPager->pWal, db, eMode,
(eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler),
pPager->pBusyHandlerArg,
- pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace,
+ pPager->walSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace,
pnLog, pnCkpt
);
}
@@ -53695,7 +55499,7 @@ SQLITE_PRIVATE int sqlite3PagerOpenWal(
** error (SQLITE_BUSY) is returned and the log connection is not closed.
** If successful, the EXCLUSIVE lock is not released before returning.
*/
-SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager){
+SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3 *db){
int rc = SQLITE_OK;
assert( pPager->journalMode==PAGER_JOURNALMODE_WAL );
@@ -53723,7 +55527,7 @@ SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager){
if( rc==SQLITE_OK && pPager->pWal ){
rc = pagerExclusiveLock(pPager);
if( rc==SQLITE_OK ){
- rc = sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags,
+ rc = sqlite3WalClose(pPager->pWal, db, pPager->walSyncFlags,
pPager->pageSize, (u8*)pPager->pTmpSpace);
pPager->pWal = 0;
pagerFixMaplimit(pPager);
@@ -53760,6 +55564,20 @@ SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSn
}
return rc;
}
+
+/*
+** If this is a WAL database, call sqlite3WalSnapshotRecover(). If this
+** is not a WAL database, return an error.
+*/
+SQLITE_PRIVATE int sqlite3PagerSnapshotRecover(Pager *pPager){
+ int rc;
+ if( pPager->pWal ){
+ rc = sqlite3WalSnapshotRecover(pPager->pWal);
+ }else{
+ rc = SQLITE_ERROR;
+ }
+ return rc;
+}
#endif /* SQLITE_ENABLE_SNAPSHOT */
#endif /* !SQLITE_OMIT_WAL */
@@ -53915,6 +55733,10 @@ SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){
** on a network filesystem. All users of the database must be able to
** share memory.
**
+** In the default unix and windows implementation, the wal-index is a mmapped
+** file whose name is the database name with a "-shm" suffix added. For that
+** reason, the wal-index is sometimes called the "shm" file.
+**
** The wal-index is transient. After a crash, the wal-index can (and should
** be) reconstructed from the original WAL file. In fact, the VFS is required
** to either truncate or zero the header of the wal-index when the last
@@ -54054,9 +55876,18 @@ SQLITE_PRIVATE int sqlite3WalTrace = 0;
#define WALINDEX_MAX_VERSION 3007000
/*
-** Indices of various locking bytes. WAL_NREADER is the number
+** Index numbers for various locking bytes. WAL_NREADER is the number
** of available reader locks and should be at least 3. The default
** is SQLITE_SHM_NLOCK==8 and WAL_NREADER==5.
+**
+** Technically, the various VFSes are free to implement these locks however
+** they see fit. However, compatibility is encouraged so that VFSes can
+** interoperate. The standard implemention used on both unix and windows
+** is for the index number to indicate a byte offset into the
+** WalCkptInfo.aLock[] array in the wal-index header. In other words, all
+** locks are on the shm file. The WALINDEX_LOCK_OFFSET constant (which
+** should be 120) is the location in the shm file for the first locking
+** byte.
*/
#define WAL_WRITE_LOCK 0
#define WAL_ALL_BUT_WRITE 1
@@ -54180,7 +56011,6 @@ struct WalCkptInfo {
#define WAL_FRAME_HDRSIZE 24
/* Size of write ahead log header, including checksum. */
-/* #define WAL_HDRSIZE 24 */
#define WAL_HDRSIZE 32
/* WAL magic value. Either this value, or the same value with the least
@@ -54226,6 +56056,7 @@ struct Wal {
u8 truncateOnCommit; /* True to truncate WAL file on commit */
u8 syncHeader; /* Fsync the WAL header if true */
u8 padToSectorBoundary; /* Pad transactions out to the next sector */
+ u8 bShmUnreliable; /* SHM content is read-only and unreliable */
WalIndexHdr hdr; /* Wal-index header for current transaction */
u32 minFrame; /* Ignore wal frames before this one */
u32 iReCksum; /* On commit, recalculate checksums from here */
@@ -54315,6 +56146,11 @@ struct WalIterator {
** is broken into pages of WALINDEX_PGSZ bytes. Wal-index pages are
** numbered from zero.
**
+** If the wal-index is currently smaller the iPage pages then the size
+** of the wal-index might be increased, but only if it is safe to do
+** so. It is safe to enlarge the wal-index if pWal->writeLock is true
+** or pWal->exclusiveMode==WAL_HEAPMEMORY_MODE.
+**
** If this call is successful, *ppPage is set to point to the wal-index
** page and SQLITE_OK is returned. If an error (an OOM or VFS error) occurs,
** then an SQLite error code is returned and *ppPage is set to 0.
@@ -54346,9 +56182,13 @@ static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){
rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ,
pWal->writeLock, (void volatile **)&pWal->apWiData[iPage]
);
- if( rc==SQLITE_READONLY ){
+ assert( pWal->apWiData[iPage]!=0 || rc!=SQLITE_OK || pWal->writeLock==0 );
+ testcase( pWal->apWiData[iPage]==0 && rc==SQLITE_OK );
+ if( (rc&0xff)==SQLITE_READONLY ){
pWal->readOnly |= WAL_SHM_RDONLY;
- rc = SQLITE_OK;
+ if( rc==SQLITE_READONLY ){
+ rc = SQLITE_OK;
+ }
}
}
}
@@ -54870,7 +56710,6 @@ static int walIndexRecover(Wal *pWal){
i64 nSize; /* Size of log file */
u32 aFrameCksum[2] = {0, 0};
int iLock; /* Lock offset to lock for checkpoint */
- int nLock; /* Number of locks to hold */
/* Obtain an exclusive lock on all byte in the locking range not already
** locked by the caller. The caller is guaranteed to have locked the
@@ -54883,11 +56722,17 @@ static int walIndexRecover(Wal *pWal){
assert( WAL_CKPT_LOCK==WAL_ALL_BUT_WRITE );
assert( pWal->writeLock );
iLock = WAL_ALL_BUT_WRITE + pWal->ckptLock;
- nLock = SQLITE_SHM_NLOCK - iLock;
- rc = walLockExclusive(pWal, iLock, nLock);
+ rc = walLockExclusive(pWal, iLock, WAL_READ_LOCK(0)-iLock);
+ if( rc==SQLITE_OK ){
+ rc = walLockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
+ if( rc!=SQLITE_OK ){
+ walUnlockExclusive(pWal, iLock, WAL_READ_LOCK(0)-iLock);
+ }
+ }
if( rc ){
return rc;
}
+
WALTRACE(("WAL%p: recovery begin...\n", pWal));
memset(&pWal->hdr, 0, sizeof(WalIndexHdr));
@@ -55025,7 +56870,8 @@ static int walIndexRecover(Wal *pWal){
recovery_error:
WALTRACE(("WAL%p: recovery %s\n", pWal, rc ? "failed" : "ok"));
- walUnlockExclusive(pWal, iLock, nLock);
+ walUnlockExclusive(pWal, iLock, WAL_READ_LOCK(0)-iLock);
+ walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
return rc;
}
@@ -55033,13 +56879,14 @@ static int walIndexRecover(Wal *pWal){
** Close an open wal-index.
*/
static void walIndexClose(Wal *pWal, int isDelete){
- if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){
+ if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE || pWal->bShmUnreliable ){
int i;
for(i=0; inWiData; i++){
sqlite3_free((void *)pWal->apWiData[i]);
pWal->apWiData[i] = 0;
}
- }else{
+ }
+ if( pWal->exclusiveMode!=WAL_HEAPMEMORY_MODE ){
sqlite3OsShmUnmap(pWal->pDbFd, isDelete);
}
}
@@ -55506,6 +57353,7 @@ static void walRestartHdr(Wal *pWal, u32 salt1){
*/
static int walCheckpoint(
Wal *pWal, /* Wal connection */
+ sqlite3 *db, /* Check for interrupts on this handle */
int eMode, /* One of PASSIVE, FULL or RESTART */
int (*xBusy)(void*), /* Function to call when busy */
void *pBusyArg, /* Context argument for xBusyHandler */
@@ -55580,9 +57428,7 @@ static int walCheckpoint(
pInfo->nBackfillAttempted = mxSafeFrame;
/* Sync the WAL to disk */
- if( sync_flags ){
- rc = sqlite3OsSync(pWal->pWalFd, sync_flags);
- }
+ rc = sqlite3OsSync(pWal->pWalFd, CKPT_SYNC_FLAGS(sync_flags));
/* If the database may grow as a result of this checkpoint, hint
** about the eventual size of the db file to the VFS layer.
@@ -55600,6 +57446,10 @@ static int walCheckpoint(
while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){
i64 iOffset;
assert( walFramePgno(pWal, iFrame)==iDbpage );
+ if( db->u1.isInterrupted ){
+ rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT;
+ break;
+ }
if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ){
continue;
}
@@ -55619,8 +57469,8 @@ static int walCheckpoint(
i64 szDb = pWal->hdr.nPage*(i64)szPage;
testcase( IS_BIG_INT(szDb) );
rc = sqlite3OsTruncate(pWal->pDbFd, szDb);
- if( rc==SQLITE_OK && sync_flags ){
- rc = sqlite3OsSync(pWal->pDbFd, sync_flags);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3OsSync(pWal->pDbFd, CKPT_SYNC_FLAGS(sync_flags));
}
}
if( rc==SQLITE_OK ){
@@ -55704,6 +57554,7 @@ static void walLimitSize(Wal *pWal, i64 nMax){
*/
SQLITE_PRIVATE int sqlite3WalClose(
Wal *pWal, /* Wal to close */
+ sqlite3 *db, /* For interrupt flag */
int sync_flags, /* Flags to pass to OsSync() (or 0) */
int nBuf,
u8 *zBuf /* Buffer of at least nBuf bytes */
@@ -55720,13 +57571,14 @@ SQLITE_PRIVATE int sqlite3WalClose(
**
** The EXCLUSIVE lock is not released before returning.
*/
- rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE);
- if( rc==SQLITE_OK ){
+ if( zBuf!=0
+ && SQLITE_OK==(rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE))
+ ){
if( pWal->exclusiveMode==WAL_NORMAL_MODE ){
pWal->exclusiveMode = WAL_EXCLUSIVE_MODE;
}
- rc = sqlite3WalCheckpoint(
- pWal, SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0
+ rc = sqlite3WalCheckpoint(pWal, db,
+ SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0
);
if( rc==SQLITE_OK ){
int bPersist = -1;
@@ -55827,6 +57679,12 @@ static int walIndexTryHdr(Wal *pWal, int *pChanged){
return 0;
}
+/*
+** This is the value that walTryBeginRead returns when it needs to
+** be retried.
+*/
+#define WAL_RETRY (-1)
+
/*
** Read the wal-index header from the wal-index and into pWal->hdr.
** If the wal-header appears to be corrupt, try to reconstruct the
@@ -55850,9 +57708,29 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){
assert( pChanged );
rc = walIndexPage(pWal, 0, &page0);
if( rc!=SQLITE_OK ){
- return rc;
- };
- assert( page0 || pWal->writeLock==0 );
+ assert( rc!=SQLITE_READONLY ); /* READONLY changed to OK in walIndexPage */
+ if( rc==SQLITE_READONLY_CANTINIT ){
+ /* The SQLITE_READONLY_CANTINIT return means that the shared-memory
+ ** was openable but is not writable, and this thread is unable to
+ ** confirm that another write-capable connection has the shared-memory
+ ** open, and hence the content of the shared-memory is unreliable,
+ ** since the shared-memory might be inconsistent with the WAL file
+ ** and there is no writer on hand to fix it. */
+ assert( page0==0 );
+ assert( pWal->writeLock==0 );
+ assert( pWal->readOnly & WAL_SHM_RDONLY );
+ pWal->bShmUnreliable = 1;
+ pWal->exclusiveMode = WAL_HEAPMEMORY_MODE;
+ *pChanged = 1;
+ }else{
+ return rc; /* Any other non-OK return is just an error */
+ }
+ }else{
+ /* page0 can be NULL if the SHM is zero bytes in size and pWal->writeLock
+ ** is zero, which prevents the SHM from growing */
+ testcase( page0!=0 );
+ }
+ assert( page0!=0 || pWal->writeLock==0 );
/* If the first page of the wal-index has been mapped, try to read the
** wal-index header immediately, without holding any lock. This usually
@@ -55866,7 +57744,7 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){
*/
assert( badHdr==0 || pWal->writeLock==0 );
if( badHdr ){
- if( pWal->readOnly & WAL_SHM_RDONLY ){
+ if( pWal->bShmUnreliable==0 && (pWal->readOnly & WAL_SHM_RDONLY) ){
if( SQLITE_OK==(rc = walLockShared(pWal, WAL_WRITE_LOCK)) ){
walUnlockShared(pWal, WAL_WRITE_LOCK);
rc = SQLITE_READONLY_RECOVERY;
@@ -55896,15 +57774,193 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){
if( badHdr==0 && pWal->hdr.iVersion!=WALINDEX_MAX_VERSION ){
rc = SQLITE_CANTOPEN_BKPT;
}
+ if( pWal->bShmUnreliable ){
+ if( rc!=SQLITE_OK ){
+ walIndexClose(pWal, 0);
+ pWal->bShmUnreliable = 0;
+ assert( pWal->nWiData>0 && pWal->apWiData[0]==0 );
+ /* walIndexRecover() might have returned SHORT_READ if a concurrent
+ ** writer truncated the WAL out from under it. If that happens, it
+ ** indicates that a writer has fixed the SHM file for us, so retry */
+ if( rc==SQLITE_IOERR_SHORT_READ ) rc = WAL_RETRY;
+ }
+ pWal->exclusiveMode = WAL_NORMAL_MODE;
+ }
return rc;
}
/*
-** This is the value that walTryBeginRead returns when it needs to
-** be retried.
+** Open a transaction in a connection where the shared-memory is read-only
+** and where we cannot verify that there is a separate write-capable connection
+** on hand to keep the shared-memory up-to-date with the WAL file.
+**
+** This can happen, for example, when the shared-memory is implemented by
+** memory-mapping a *-shm file, where a prior writer has shut down and
+** left the *-shm file on disk, and now the present connection is trying
+** to use that database but lacks write permission on the *-shm file.
+** Other scenarios are also possible, depending on the VFS implementation.
+**
+** Precondition:
+**
+** The *-wal file has been read and an appropriate wal-index has been
+** constructed in pWal->apWiData[] using heap memory instead of shared
+** memory.
+**
+** If this function returns SQLITE_OK, then the read transaction has
+** been successfully opened. In this case output variable (*pChanged)
+** is set to true before returning if the caller should discard the
+** contents of the page cache before proceeding. Or, if it returns
+** WAL_RETRY, then the heap memory wal-index has been discarded and
+** the caller should retry opening the read transaction from the
+** beginning (including attempting to map the *-shm file).
+**
+** If an error occurs, an SQLite error code is returned.
*/
-#define WAL_RETRY (-1)
+static int walBeginShmUnreliable(Wal *pWal, int *pChanged){
+ i64 szWal; /* Size of wal file on disk in bytes */
+ i64 iOffset; /* Current offset when reading wal file */
+ u8 aBuf[WAL_HDRSIZE]; /* Buffer to load WAL header into */
+ u8 *aFrame = 0; /* Malloc'd buffer to load entire frame */
+ int szFrame; /* Number of bytes in buffer aFrame[] */
+ u8 *aData; /* Pointer to data part of aFrame buffer */
+ volatile void *pDummy; /* Dummy argument for xShmMap */
+ int rc; /* Return code */
+ u32 aSaveCksum[2]; /* Saved copy of pWal->hdr.aFrameCksum */
+
+ assert( pWal->bShmUnreliable );
+ assert( pWal->readOnly & WAL_SHM_RDONLY );
+ assert( pWal->nWiData>0 && pWal->apWiData[0] );
+
+ /* Take WAL_READ_LOCK(0). This has the effect of preventing any
+ ** writers from running a checkpoint, but does not stop them
+ ** from running recovery. */
+ rc = walLockShared(pWal, WAL_READ_LOCK(0));
+ if( rc!=SQLITE_OK ){
+ if( rc==SQLITE_BUSY ) rc = WAL_RETRY;
+ goto begin_unreliable_shm_out;
+ }
+ pWal->readLock = 0;
+
+ /* Check to see if a separate writer has attached to the shared-memory area,
+ ** thus making the shared-memory "reliable" again. Do this by invoking
+ ** the xShmMap() routine of the VFS and looking to see if the return
+ ** is SQLITE_READONLY instead of SQLITE_READONLY_CANTINIT.
+ **
+ ** If the shared-memory is now "reliable" return WAL_RETRY, which will
+ ** cause the heap-memory WAL-index to be discarded and the actual
+ ** shared memory to be used in its place.
+ **
+ ** This step is important because, even though this connection is holding
+ ** the WAL_READ_LOCK(0) which prevents a checkpoint, a writer might
+ ** have already checkpointed the WAL file and, while the current
+ ** is active, wrap the WAL and start overwriting frames that this
+ ** process wants to use.
+ **
+ ** Once sqlite3OsShmMap() has been called for an sqlite3_file and has
+ ** returned any SQLITE_READONLY value, it must return only SQLITE_READONLY
+ ** or SQLITE_READONLY_CANTINIT or some error for all subsequent invocations,
+ ** even if some external agent does a "chmod" to make the shared-memory
+ ** writable by us, until sqlite3OsShmUnmap() has been called.
+ ** This is a requirement on the VFS implementation.
+ */
+ rc = sqlite3OsShmMap(pWal->pDbFd, 0, WALINDEX_PGSZ, 0, &pDummy);
+ assert( rc!=SQLITE_OK ); /* SQLITE_OK not possible for read-only connection */
+ if( rc!=SQLITE_READONLY_CANTINIT ){
+ rc = (rc==SQLITE_READONLY ? WAL_RETRY : rc);
+ goto begin_unreliable_shm_out;
+ }
+
+ /* We reach this point only if the real shared-memory is still unreliable.
+ ** Assume the in-memory WAL-index substitute is correct and load it
+ ** into pWal->hdr.
+ */
+ memcpy(&pWal->hdr, (void*)walIndexHdr(pWal), sizeof(WalIndexHdr));
+
+ /* Make sure some writer hasn't come in and changed the WAL file out
+ ** from under us, then disconnected, while we were not looking.
+ */
+ rc = sqlite3OsFileSize(pWal->pWalFd, &szWal);
+ if( rc!=SQLITE_OK ){
+ goto begin_unreliable_shm_out;
+ }
+ if( szWalhdr.mxFrame==0 ? SQLITE_OK : WAL_RETRY);
+ goto begin_unreliable_shm_out;
+ }
+
+ /* Check the salt keys at the start of the wal file still match. */
+ rc = sqlite3OsRead(pWal->pWalFd, aBuf, WAL_HDRSIZE, 0);
+ if( rc!=SQLITE_OK ){
+ goto begin_unreliable_shm_out;
+ }
+ if( memcmp(&pWal->hdr.aSalt, &aBuf[16], 8) ){
+ /* Some writer has wrapped the WAL file while we were not looking.
+ ** Return WAL_RETRY which will cause the in-memory WAL-index to be
+ ** rebuilt. */
+ rc = WAL_RETRY;
+ goto begin_unreliable_shm_out;
+ }
+
+ /* Allocate a buffer to read frames into */
+ szFrame = pWal->hdr.szPage + WAL_FRAME_HDRSIZE;
+ aFrame = (u8 *)sqlite3_malloc64(szFrame);
+ if( aFrame==0 ){
+ rc = SQLITE_NOMEM_BKPT;
+ goto begin_unreliable_shm_out;
+ }
+ aData = &aFrame[WAL_FRAME_HDRSIZE];
+
+ /* Check to see if a complete transaction has been appended to the
+ ** wal file since the heap-memory wal-index was created. If so, the
+ ** heap-memory wal-index is discarded and WAL_RETRY returned to
+ ** the caller. */
+ aSaveCksum[0] = pWal->hdr.aFrameCksum[0];
+ aSaveCksum[1] = pWal->hdr.aFrameCksum[1];
+ for(iOffset=walFrameOffset(pWal->hdr.mxFrame+1, pWal->hdr.szPage);
+ iOffset+szFrame<=szWal;
+ iOffset+=szFrame
+ ){
+ u32 pgno; /* Database page number for frame */
+ u32 nTruncate; /* dbsize field from frame header */
+
+ /* Read and decode the next log frame. */
+ rc = sqlite3OsRead(pWal->pWalFd, aFrame, szFrame, iOffset);
+ if( rc!=SQLITE_OK ) break;
+ if( !walDecodeFrame(pWal, &pgno, &nTruncate, aData, aFrame) ) break;
+
+ /* If nTruncate is non-zero, then a complete transaction has been
+ ** appended to this wal file. Set rc to WAL_RETRY and break out of
+ ** the loop. */
+ if( nTruncate ){
+ rc = WAL_RETRY;
+ break;
+ }
+ }
+ pWal->hdr.aFrameCksum[0] = aSaveCksum[0];
+ pWal->hdr.aFrameCksum[1] = aSaveCksum[1];
+
+ begin_unreliable_shm_out:
+ sqlite3_free(aFrame);
+ if( rc!=SQLITE_OK ){
+ int i;
+ for(i=0; inWiData; i++){
+ sqlite3_free((void*)pWal->apWiData[i]);
+ pWal->apWiData[i] = 0;
+ }
+ pWal->bShmUnreliable = 0;
+ sqlite3WalEndReadTransaction(pWal);
+ *pChanged = 1;
+ }
+ return rc;
+}
/*
** Attempt to start a read transaction. This might fail due to a race or
@@ -55920,7 +57976,7 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){
** checkpointed. If useWal==0 then this routine calls walIndexReadHdr()
** to make a copy of the wal-index header into pWal->hdr. If the
** wal-index header has changed, *pChanged is set to 1 (as an indication
-** to the caller that the local paget cache is obsolete and needs to be
+** to the caller that the local page cache is obsolete and needs to be
** flushed.) When useWal==1, the wal-index header is assumed to already
** be loaded and the pChanged parameter is unused.
**
@@ -55966,6 +58022,9 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
assert( pWal->readLock<0 ); /* Not currently locked */
+ /* useWal may only be set for read/write connections */
+ assert( (pWal->readOnly & WAL_SHM_RDONLY)==0 || useWal==0 );
+
/* Take steps to avoid spinning forever if there is a protocol error.
**
** Circumstances that cause a RETRY should only last for the briefest
@@ -55994,7 +58053,10 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
}
if( !useWal ){
- rc = walIndexReadHdr(pWal, pChanged);
+ assert( rc==SQLITE_OK );
+ if( pWal->bShmUnreliable==0 ){
+ rc = walIndexReadHdr(pWal, pChanged);
+ }
if( rc==SQLITE_BUSY ){
/* If there is not a recovery running in another thread or process
** then convert BUSY errors to WAL_RETRY. If recovery is known to
@@ -56023,13 +58085,17 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
if( rc!=SQLITE_OK ){
return rc;
}
+ else if( pWal->bShmUnreliable ){
+ return walBeginShmUnreliable(pWal, pChanged);
+ }
}
+ assert( pWal->nWiData>0 );
+ assert( pWal->apWiData[0]!=0 );
pInfo = walCkptInfo(pWal);
- if( !useWal && pInfo->nBackfill==pWal->hdr.mxFrame
+ if( !useWal && pInfo->nBackfill==pWal->hdr.mxFrame
#ifdef SQLITE_ENABLE_SNAPSHOT
- && (pWal->pSnapshot==0 || pWal->hdr.mxFrame==0
- || 0==memcmp(&pWal->hdr, pWal->pSnapshot, sizeof(WalIndexHdr)))
+ && (pWal->pSnapshot==0 || pWal->hdr.mxFrame==0)
#endif
){
/* The WAL has been completely backfilled (or it is empty).
@@ -56100,7 +58166,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
}
if( mxI==0 ){
assert( rc==SQLITE_BUSY || (pWal->readOnly & WAL_SHM_RDONLY)!=0 );
- return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTLOCK;
+ return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTINIT;
}
rc = walLockShared(pWal, WAL_READ_LOCK(mxI));
@@ -56155,6 +58221,84 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
return rc;
}
+#ifdef SQLITE_ENABLE_SNAPSHOT
+/*
+** Attempt to reduce the value of the WalCkptInfo.nBackfillAttempted
+** variable so that older snapshots can be accessed. To do this, loop
+** through all wal frames from nBackfillAttempted to (nBackfill+1),
+** comparing their content to the corresponding page with the database
+** file, if any. Set nBackfillAttempted to the frame number of the
+** first frame for which the wal file content matches the db file.
+**
+** This is only really safe if the file-system is such that any page
+** writes made by earlier checkpointers were atomic operations, which
+** is not always true. It is also possible that nBackfillAttempted
+** may be left set to a value larger than expected, if a wal frame
+** contains content that duplicate of an earlier version of the same
+** page.
+**
+** SQLITE_OK is returned if successful, or an SQLite error code if an
+** error occurs. It is not an error if nBackfillAttempted cannot be
+** decreased at all.
+*/
+SQLITE_PRIVATE int sqlite3WalSnapshotRecover(Wal *pWal){
+ int rc;
+
+ assert( pWal->readLock>=0 );
+ rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
+ if( rc==SQLITE_OK ){
+ volatile WalCkptInfo *pInfo = walCkptInfo(pWal);
+ int szPage = (int)pWal->szPage;
+ i64 szDb; /* Size of db file in bytes */
+
+ rc = sqlite3OsFileSize(pWal->pDbFd, &szDb);
+ if( rc==SQLITE_OK ){
+ void *pBuf1 = sqlite3_malloc(szPage);
+ void *pBuf2 = sqlite3_malloc(szPage);
+ if( pBuf1==0 || pBuf2==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ u32 i = pInfo->nBackfillAttempted;
+ for(i=pInfo->nBackfillAttempted; i>pInfo->nBackfill; i--){
+ volatile ht_slot *dummy;
+ volatile u32 *aPgno; /* Array of page numbers */
+ u32 iZero; /* Frame corresponding to aPgno[0] */
+ u32 pgno; /* Page number in db file */
+ i64 iDbOff; /* Offset of db file entry */
+ i64 iWalOff; /* Offset of wal file entry */
+
+ rc = walHashGet(pWal, walFramePage(i), &dummy, &aPgno, &iZero);
+ if( rc!=SQLITE_OK ) break;
+ pgno = aPgno[i-iZero];
+ iDbOff = (i64)(pgno-1) * szPage;
+
+ if( iDbOff+szPage<=szDb ){
+ iWalOff = walFrameOffset(i, szPage) + WAL_FRAME_HDRSIZE;
+ rc = sqlite3OsRead(pWal->pWalFd, pBuf1, szPage, iWalOff);
+
+ if( rc==SQLITE_OK ){
+ rc = sqlite3OsRead(pWal->pDbFd, pBuf2, szPage, iDbOff);
+ }
+
+ if( rc!=SQLITE_OK || 0==memcmp(pBuf1, pBuf2, szPage) ){
+ break;
+ }
+ }
+
+ pInfo->nBackfillAttempted = i-1;
+ }
+ }
+
+ sqlite3_free(pBuf1);
+ sqlite3_free(pBuf2);
+ }
+ walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1);
+ }
+
+ return rc;
+}
+#endif /* SQLITE_ENABLE_SNAPSHOT */
+
/*
** Begin a read transaction on the database.
**
@@ -56217,7 +58361,11 @@ SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
** has not yet set the pInfo->nBackfillAttempted variable to indicate
** its intent. To avoid the race condition this leads to, ensure that
** there is no checkpointer process by taking a shared CKPT lock
- ** before checking pInfo->nBackfillAttempted. */
+ ** before checking pInfo->nBackfillAttempted.
+ **
+ ** TODO: Does the aReadMark[] lock prevent a checkpointer from doing
+ ** this already?
+ */
rc = walLockShared(pWal, WAL_CKPT_LOCK);
if( rc==SQLITE_OK ){
@@ -56290,7 +58438,7 @@ SQLITE_PRIVATE int sqlite3WalFindFrame(
** then the WAL is ignored by the reader so return early, as if the
** WAL were empty.
*/
- if( iLast==0 || pWal->readLock==0 ){
+ if( iLast==0 || (pWal->readLock==0 && pWal->bShmUnreliable==0) ){
*piRead = 0;
return SQLITE_OK;
}
@@ -56353,8 +58501,8 @@ SQLITE_PRIVATE int sqlite3WalFindFrame(
{
u32 iRead2 = 0;
u32 iTest;
- assert( pWal->minFrame>0 );
- for(iTest=iLast; iTest>=pWal->minFrame; iTest--){
+ assert( pWal->bShmUnreliable || pWal->minFrame>0 );
+ for(iTest=iLast; iTest>=pWal->minFrame && iTest>0; iTest--){
if( walFramePgno(pWal, iTest)==pgno ){
iRead2 = iTest;
break;
@@ -56642,8 +58790,8 @@ static int walWriteToLog(
iOffset += iFirstAmt;
iAmt -= iFirstAmt;
pContent = (void*)(iFirstAmt + (char*)pContent);
- assert( p->syncFlags & (SQLITE_SYNC_NORMAL|SQLITE_SYNC_FULL) );
- rc = sqlite3OsSync(p->pFd, p->syncFlags & SQLITE_SYNC_MASK);
+ assert( WAL_SYNC_FLAGS(p->syncFlags)!=0 );
+ rc = sqlite3OsSync(p->pFd, WAL_SYNC_FLAGS(p->syncFlags));
if( iAmt==0 || rc ) return rc;
}
rc = sqlite3OsWrite(p->pFd, pContent, iAmt, iOffset);
@@ -56813,10 +58961,10 @@ SQLITE_PRIVATE int sqlite3WalFrames(
** an out-of-order write following a WAL restart could result in
** database corruption. See the ticket:
**
- ** http://localhost:591/sqlite/info/ff5be73dee
+ ** https://sqlite.org/src/info/ff5be73dee
*/
- if( pWal->syncHeader && sync_flags ){
- rc = sqlite3OsSync(pWal->pWalFd, sync_flags & SQLITE_SYNC_MASK);
+ if( pWal->syncHeader ){
+ rc = sqlite3OsSync(pWal->pWalFd, CKPT_SYNC_FLAGS(sync_flags));
if( rc ) return rc;
}
}
@@ -56891,7 +59039,7 @@ SQLITE_PRIVATE int sqlite3WalFrames(
** sector boundary is synced; the part of the last frame that extends
** past the sector boundary is written after the sync.
*/
- if( isCommit && (sync_flags & WAL_SYNC_TRANSACTIONS)!=0 ){
+ if( isCommit && WAL_SYNC_FLAGS(sync_flags)!=0 ){
int bSync = 1;
if( pWal->padToSectorBoundary ){
int sectorSize = sqlite3SectorSize(pWal->pWalFd);
@@ -56907,7 +59055,7 @@ SQLITE_PRIVATE int sqlite3WalFrames(
}
if( bSync ){
assert( rc==SQLITE_OK );
- rc = sqlite3OsSync(w.pFd, sync_flags & SQLITE_SYNC_MASK);
+ rc = sqlite3OsSync(w.pFd, WAL_SYNC_FLAGS(sync_flags));
}
}
@@ -56974,6 +59122,7 @@ SQLITE_PRIVATE int sqlite3WalFrames(
*/
SQLITE_PRIVATE int sqlite3WalCheckpoint(
Wal *pWal, /* Wal connection */
+ sqlite3 *db, /* Check this handle's interrupt flag */
int eMode, /* PASSIVE, FULL, RESTART, or TRUNCATE */
int (*xBusy)(void*), /* Function to call when busy */
void *pBusyArg, /* Context argument for xBusyHandler */
@@ -57048,7 +59197,7 @@ SQLITE_PRIVATE int sqlite3WalCheckpoint(
if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){
rc = SQLITE_CORRUPT_BKPT;
}else{
- rc = walCheckpoint(pWal, eMode2, xBusy2, pBusyArg, sync_flags, zBuf);
+ rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags, zBuf);
}
/* If no error occurred, set the output variables. */
@@ -57129,24 +59278,24 @@ SQLITE_PRIVATE int sqlite3WalExclusiveMode(Wal *pWal, int op){
assert( pWal->readLock>=0 || (op<=0 && pWal->exclusiveMode==0) );
if( op==0 ){
- if( pWal->exclusiveMode ){
- pWal->exclusiveMode = 0;
+ if( pWal->exclusiveMode!=WAL_NORMAL_MODE ){
+ pWal->exclusiveMode = WAL_NORMAL_MODE;
if( walLockShared(pWal, WAL_READ_LOCK(pWal->readLock))!=SQLITE_OK ){
- pWal->exclusiveMode = 1;
+ pWal->exclusiveMode = WAL_EXCLUSIVE_MODE;
}
- rc = pWal->exclusiveMode==0;
+ rc = pWal->exclusiveMode==WAL_NORMAL_MODE;
}else{
/* Already in locking_mode=NORMAL */
rc = 0;
}
}else if( op>0 ){
- assert( pWal->exclusiveMode==0 );
+ assert( pWal->exclusiveMode==WAL_NORMAL_MODE );
assert( pWal->readLock>=0 );
walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock));
- pWal->exclusiveMode = 1;
+ pWal->exclusiveMode = WAL_EXCLUSIVE_MODE;
rc = 1;
}else{
- rc = pWal->exclusiveMode==0;
+ rc = pWal->exclusiveMode==WAL_NORMAL_MODE;
}
return rc;
}
@@ -57168,9 +59317,14 @@ SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal){
SQLITE_PRIVATE int sqlite3WalSnapshotGet(Wal *pWal, sqlite3_snapshot **ppSnapshot){
int rc = SQLITE_OK;
WalIndexHdr *pRet;
+ static const u32 aZero[4] = { 0, 0, 0, 0 };
assert( pWal->readLock>=0 && pWal->writeLock==0 );
+ if( memcmp(&pWal->hdr.aFrameCksum[0],aZero,16)==0 ){
+ *ppSnapshot = 0;
+ return SQLITE_ERROR;
+ }
pRet = (WalIndexHdr*)sqlite3_malloc(sizeof(WalIndexHdr));
if( pRet==0 ){
rc = SQLITE_NOMEM_BKPT;
@@ -57508,37 +59662,39 @@ typedef struct CellInfo CellInfo;
#define PTF_LEAF 0x08
/*
-** As each page of the file is loaded into memory, an instance of the following
-** structure is appended and initialized to zero. This structure stores
-** information about the page that is decoded from the raw file page.
+** An instance of this object stores information about each a single database
+** page that has been loaded into memory. The information in this object
+** is derived from the raw on-disk page content.
**
-** The pParent field points back to the parent page. This allows us to
-** walk up the BTree from any leaf to the root. Care must be taken to
-** unref() the parent page pointer when this page is no longer referenced.
-** The pageDestructor() routine handles that chore.
+** As each database page is loaded into memory, the pager allocats an
+** instance of this object and zeros the first 8 bytes. (This is the
+** "extra" information associated with each page of the pager.)
**
** Access to all fields of this structure is controlled by the mutex
** stored in MemPage.pBt->mutex.
*/
struct MemPage {
u8 isInit; /* True if previously initialized. MUST BE FIRST! */
- u8 nOverflow; /* Number of overflow cell bodies in aCell[] */
+ u8 bBusy; /* Prevent endless loops on corrupt database files */
u8 intKey; /* True if table b-trees. False for index b-trees */
u8 intKeyLeaf; /* True if the leaf of an intKey table */
+ Pgno pgno; /* Page number for this page */
+ /* Only the first 8 bytes (above) are zeroed by pager.c when a new page
+ ** is allocated. All fields that follow must be initialized before use */
u8 leaf; /* True if a leaf page */
u8 hdrOffset; /* 100 for page 1. 0 otherwise */
u8 childPtrSize; /* 0 if leaf==1. 4 if leaf==0 */
u8 max1bytePayload; /* min(maxLocal,127) */
- u8 bBusy; /* Prevent endless loops on corrupt database files */
+ u8 nOverflow; /* Number of overflow cell bodies in aCell[] */
u16 maxLocal; /* Copy of BtShared.maxLocal or BtShared.maxLeaf */
u16 minLocal; /* Copy of BtShared.minLocal or BtShared.minLeaf */
u16 cellOffset; /* Index in aData of first cell pointer */
u16 nFree; /* Number of free bytes on the page */
u16 nCell; /* Number of cells on this page, local and ovfl */
u16 maskPage; /* Mask for page offset */
- u16 aiOvfl[5]; /* Insert the i-th overflow cell before the aiOvfl-th
+ u16 aiOvfl[4]; /* Insert the i-th overflow cell before the aiOvfl-th
** non-overflow cell */
- u8 *apOvfl[5]; /* Pointers to the body of overflow cells */
+ u8 *apOvfl[4]; /* Pointers to the body of overflow cells */
BtShared *pBt; /* Pointer to BtShared that this page is part of */
u8 *aData; /* Pointer to disk image of the page data */
u8 *aDataEnd; /* One byte past the end of usable data */
@@ -57547,16 +59703,8 @@ struct MemPage {
DbPage *pDbPage; /* Pager page handle */
u16 (*xCellSize)(MemPage*,u8*); /* cellSizePtr method */
void (*xParseCell)(MemPage*,u8*,CellInfo*); /* btreeParseCell method */
- Pgno pgno; /* Page number for this page */
};
-/*
-** The in-memory image of a disk page has the auxiliary information appended
-** to the end. EXTRA_SIZE is the number of bytes of space needed to hold
-** that extra information.
-*/
-#define EXTRA_SIZE sizeof(MemPage)
-
/*
** A linked list of the following structures is stored at BtShared.pLock.
** Locks are added (or upgraded from READ_LOCK to WRITE_LOCK) when a cursor
@@ -57703,10 +59851,12 @@ struct BtShared {
#define BTS_READ_ONLY 0x0001 /* Underlying file is readonly */
#define BTS_PAGESIZE_FIXED 0x0002 /* Page size can no longer be changed */
#define BTS_SECURE_DELETE 0x0004 /* PRAGMA secure_delete is enabled */
-#define BTS_INITIALLY_EMPTY 0x0008 /* Database was empty at trans start */
-#define BTS_NO_WAL 0x0010 /* Do not open write-ahead-log files */
-#define BTS_EXCLUSIVE 0x0020 /* pWriter has an exclusive lock */
-#define BTS_PENDING 0x0040 /* Waiting for read-locks to clear */
+#define BTS_OVERWRITE 0x0008 /* Overwrite deleted content with zeros */
+#define BTS_FAST_SECURE 0x000c /* Combination of the previous two */
+#define BTS_INITIALLY_EMPTY 0x0010 /* Database was empty at trans start */
+#define BTS_NO_WAL 0x0020 /* Do not open write-ahead-log files */
+#define BTS_EXCLUSIVE 0x0040 /* pWriter has an exclusive lock */
+#define BTS_PENDING 0x0080 /* Waiting for read-locks to clear */
/*
** An instance of the following structure is used to hold information
@@ -57752,6 +59902,11 @@ struct CellInfo {
** eState==FAULT: Cursor fault with skipNext as error code.
*/
struct BtCursor {
+ u8 eState; /* One of the CURSOR_XXX constants (see below) */
+ u8 curFlags; /* zero or more BTCF_* flags defined below */
+ u8 curPagerFlags; /* Flags to send to sqlite3PagerGet() */
+ u8 hints; /* As configured by CursorSetHints() */
+ int nOvflAlloc; /* Allocated size of aOverflow[] array */
Btree *pBtree; /* The Btree to which this cursor belongs */
BtShared *pBt; /* The BtShared this cursor points to */
BtCursor *pNext; /* Forms a linked list of all cursors */
@@ -57760,22 +59915,18 @@ struct BtCursor {
i64 nKey; /* Size of pKey, or last integer key */
void *pKey; /* Saved key that was cursor last known position */
Pgno pgnoRoot; /* The root page of this tree */
- int nOvflAlloc; /* Allocated size of aOverflow[] array */
int skipNext; /* Prev() is noop if negative. Next() is noop if positive.
** Error code if eState==CURSOR_FAULT */
- u8 curFlags; /* zero or more BTCF_* flags defined below */
- u8 curPagerFlags; /* Flags to send to sqlite3PagerGet() */
- u8 eState; /* One of the CURSOR_XXX constants (see below) */
- u8 hints; /* As configured by CursorSetHints() */
/* All fields above are zeroed when the cursor is allocated. See
** sqlite3BtreeCursorZero(). Fields that follow must be manually
** initialized. */
i8 iPage; /* Index of current page in apPage */
u8 curIntKey; /* Value of apPage[0]->intKey */
- struct KeyInfo *pKeyInfo; /* Argument passed to comparison function */
- void *padding1; /* Make object size a multiple of 16 */
- u16 aiIdx[BTCURSOR_MAX_DEPTH]; /* Current index in apPage[i] */
- MemPage *apPage[BTCURSOR_MAX_DEPTH]; /* Pages from root to current page */
+ u16 ix; /* Current index for apPage[iPage] */
+ u16 aiIdx[BTCURSOR_MAX_DEPTH-1]; /* Current index in apPage[i] */
+ struct KeyInfo *pKeyInfo; /* Arg passed to comparison function */
+ MemPage *pPage; /* Current page */
+ MemPage *apPage[BTCURSOR_MAX_DEPTH-1]; /* Stack of parents of current page */
};
/*
@@ -57947,11 +60098,9 @@ struct IntegrityCk {
*/
#if SQLITE_BYTEORDER==4321
# define get2byteAligned(x) (*(u16*)(x))
-#elif SQLITE_BYTEORDER==1234 && !defined(SQLITE_DISABLE_INTRINSIC) \
- && GCC_VERSION>=4008000
+#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4008000
# define get2byteAligned(x) __builtin_bswap16(*(u16*)(x))
-#elif SQLITE_BYTEORDER==1234 && !defined(SQLITE_DISABLE_INTRINSIC) \
- && defined(_MSC_VER) && _MSC_VER>=1300
+#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
# define get2byteAligned(x) _byteswap_ushort(*(u16*)(x))
#else
# define get2byteAligned(x) ((x)[0]<<8 | (x)[1])
@@ -58126,16 +60275,24 @@ SQLITE_PRIVATE int sqlite3BtreeHoldsMutex(Btree *p){
** two or more btrees in common both try to lock all their btrees
** at the same instant.
*/
-SQLITE_PRIVATE void sqlite3BtreeEnterAll(sqlite3 *db){
+static void SQLITE_NOINLINE btreeEnterAll(sqlite3 *db){
int i;
+ int skipOk = 1;
Btree *p;
assert( sqlite3_mutex_held(db->mutex) );
for(i=0; inDb; i++){
p = db->aDb[i].pBt;
- if( p ) sqlite3BtreeEnter(p);
+ if( p && p->sharable ){
+ sqlite3BtreeEnter(p);
+ skipOk = 0;
+ }
}
+ db->skipBtreeMutex = skipOk;
}
-SQLITE_PRIVATE void sqlite3BtreeLeaveAll(sqlite3 *db){
+SQLITE_PRIVATE void sqlite3BtreeEnterAll(sqlite3 *db){
+ if( db->skipBtreeMutex==0 ) btreeEnterAll(db);
+}
+static void SQLITE_NOINLINE btreeLeaveAll(sqlite3 *db){
int i;
Btree *p;
assert( sqlite3_mutex_held(db->mutex) );
@@ -58144,6 +60301,9 @@ SQLITE_PRIVATE void sqlite3BtreeLeaveAll(sqlite3 *db){
if( p ) sqlite3BtreeLeave(p);
}
}
+SQLITE_PRIVATE void sqlite3BtreeLeaveAll(sqlite3 *db){
+ if( db->skipBtreeMutex==0 ) btreeLeaveAll(db);
+}
#ifndef NDEBUG
/*
@@ -58355,6 +60515,34 @@ SQLITE_API int sqlite3_enable_shared_cache(int enable){
#define hasReadConflicts(a, b) 0
#endif
+/*
+** Implementation of the SQLITE_CORRUPT_PAGE() macro. Takes a single
+** (MemPage*) as an argument. The (MemPage*) must not be NULL.
+**
+** If SQLITE_DEBUG is not defined, then this macro is equivalent to
+** SQLITE_CORRUPT_BKPT. Or, if SQLITE_DEBUG is set, then the log message
+** normally produced as a side-effect of SQLITE_CORRUPT_BKPT is augmented
+** with the page number and filename associated with the (MemPage*).
+*/
+#ifdef SQLITE_DEBUG
+int corruptPageError(int lineno, MemPage *p){
+ char *zMsg;
+ sqlite3BeginBenignMalloc();
+ zMsg = sqlite3_mprintf("database corruption page %d of %s",
+ (int)p->pgno, sqlite3PagerFilename(p->pBt->pPager, 0)
+ );
+ sqlite3EndBenignMalloc();
+ if( zMsg ){
+ sqlite3ReportError(SQLITE_CORRUPT, lineno, zMsg);
+ }
+ sqlite3_free(zMsg);
+ return SQLITE_CORRUPT_BKPT;
+}
+# define SQLITE_CORRUPT_PAGE(pMemPage) corruptPageError(__LINE__, pMemPage)
+#else
+# define SQLITE_CORRUPT_PAGE(pMemPage) SQLITE_CORRUPT_PGNO(pMemPage->pgno)
+#endif
+
#ifndef SQLITE_OMIT_SHARED_CACHE
#ifdef SQLITE_DEBUG
@@ -58395,7 +60583,7 @@ static int hasSharedCacheTableLock(
** Return true immediately.
*/
if( (pBtree->sharable==0)
- || (eLockType==READ_LOCK && (pBtree->db->flags & SQLITE_ReadUncommitted))
+ || (eLockType==READ_LOCK && (pBtree->db->flags & SQLITE_ReadUncommit))
){
return 1;
}
@@ -58472,7 +60660,7 @@ static int hasReadConflicts(Btree *pBtree, Pgno iRoot){
for(p=pBtree->pBt->pCursor; p; p=p->pNext){
if( p->pgnoRoot==iRoot
&& p->pBtree!=pBtree
- && 0==(p->pBtree->db->flags & SQLITE_ReadUncommitted)
+ && 0==(p->pBtree->db->flags & SQLITE_ReadUncommit)
){
return 1;
}
@@ -58494,7 +60682,7 @@ static int querySharedCacheTableLock(Btree *p, Pgno iTab, u8 eLock){
assert( sqlite3BtreeHoldsMutex(p) );
assert( eLock==READ_LOCK || eLock==WRITE_LOCK );
assert( p->db!=0 );
- assert( !(p->db->flags&SQLITE_ReadUncommitted)||eLock==WRITE_LOCK||iTab==1 );
+ assert( !(p->db->flags&SQLITE_ReadUncommit)||eLock==WRITE_LOCK||iTab==1 );
/* If requesting a write-lock, then the Btree must have an open write
** transaction on this file. And, obviously, for this to be so there
@@ -58572,7 +60760,7 @@ static int setSharedCacheTableLock(Btree *p, Pgno iTable, u8 eLock){
** obtain a read-lock using this function. The only read-lock obtained
** by a connection in read-uncommitted mode is on the sqlite_master
** table, and that lock is obtained in BtreeBeginTrans(). */
- assert( 0==(p->db->flags&SQLITE_ReadUncommitted) || eLock==WRITE_LOCK );
+ assert( 0==(p->db->flags&SQLITE_ReadUncommit) || eLock==WRITE_LOCK );
/* This function should only be called on a sharable b-tree after it
** has been determined that no other b-tree holds a conflicting lock. */
@@ -58682,7 +60870,9 @@ static void downgradeAllSharedCacheTableLocks(Btree *p){
#endif /* SQLITE_OMIT_SHARED_CACHE */
-static void releasePage(MemPage *pPage); /* Forward reference */
+static void releasePage(MemPage *pPage); /* Forward reference */
+static void releasePageOne(MemPage *pPage); /* Forward reference */
+static void releasePageNotNull(MemPage *pPage); /* Forward reference */
/*
***** This routine is used inside of assert() only ****
@@ -58742,6 +60932,7 @@ static void invalidateAllOverflowCache(BtShared *pBt){
*/
static void invalidateIncrblobCursors(
Btree *pBtree, /* The database file to check */
+ Pgno pgnoRoot, /* The table that might be changing */
i64 iRow, /* The rowid that might be changing */
int isClearTable /* True if all rows are being deleted */
){
@@ -58752,7 +60943,7 @@ static void invalidateIncrblobCursors(
for(p=pBtree->pBt->pCursor; p; p=p->pNext){
if( (p->curFlags & BTCF_Incrblob)!=0 ){
pBtree->hasIncrblobCur = 1;
- if( isClearTable || p->info.nKey==iRow ){
+ if( p->pgnoRoot==pgnoRoot && (isClearTable || p->info.nKey==iRow) ){
p->eState = CURSOR_INVALID;
}
}
@@ -58761,7 +60952,7 @@ static void invalidateIncrblobCursors(
#else
/* Stub function when INCRBLOB is omitted */
- #define invalidateIncrblobCursors(x,y,z)
+ #define invalidateIncrblobCursors(w,x,y,z)
#endif /* SQLITE_OMIT_INCRBLOB */
/*
@@ -58840,11 +61031,13 @@ static void btreeClearHasContent(BtShared *pBt){
*/
static void btreeReleaseAllCursorPages(BtCursor *pCur){
int i;
- for(i=0; i<=pCur->iPage; i++){
- releasePage(pCur->apPage[i]);
- pCur->apPage[i] = 0;
+ if( pCur->iPage>=0 ){
+ for(i=0; iiPage; i++){
+ releasePageNotNull(pCur->apPage[i]);
+ }
+ releasePageNotNull(pCur->pPage);
+ pCur->iPage = -1;
}
- pCur->iPage = -1;
}
/*
@@ -58875,7 +61068,7 @@ static int saveCursorKey(BtCursor *pCur){
pCur->nKey = sqlite3BtreePayloadSize(pCur);
pKey = sqlite3Malloc( pCur->nKey );
if( pKey ){
- rc = sqlite3BtreeKey(pCur, 0, (int)pCur->nKey, pKey);
+ rc = sqlite3BtreePayload(pCur, 0, (int)pCur->nKey, pKey);
if( rc==SQLITE_OK ){
pCur->pKey = pKey;
}else{
@@ -58973,7 +61166,7 @@ static int SQLITE_NOINLINE saveCursorsOnList(
return rc;
}
}else{
- testcase( p->iPage>0 );
+ testcase( p->iPage>=0 );
btreeReleaseAllCursorPages(p);
}
}
@@ -59006,26 +61199,23 @@ static int btreeMoveto(
){
int rc; /* Status code */
UnpackedRecord *pIdxKey; /* Unpacked index key */
- char aSpace[384]; /* Temp space for pIdxKey - to avoid a malloc */
- char *pFree = 0;
if( pKey ){
assert( nKey==(i64)(int)nKey );
- pIdxKey = sqlite3VdbeAllocUnpackedRecord(
- pCur->pKeyInfo, aSpace, sizeof(aSpace), &pFree
- );
+ pIdxKey = sqlite3VdbeAllocUnpackedRecord(pCur->pKeyInfo);
if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT;
sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, pIdxKey);
if( pIdxKey->nField==0 ){
- sqlite3DbFree(pCur->pKeyInfo->db, pFree);
- return SQLITE_CORRUPT_BKPT;
+ rc = SQLITE_CORRUPT_BKPT;
+ goto moveto_done;
}
}else{
pIdxKey = 0;
}
rc = sqlite3BtreeMovetoUnpacked(pCur, pIdxKey, nKey, bias, pRes);
- if( pFree ){
- sqlite3DbFree(pCur->pKeyInfo->db, pFree);
+moveto_done:
+ if( pIdxKey ){
+ sqlite3DbFree(pCur->pKeyInfo->db, pIdxKey);
}
return rc;
}
@@ -59080,6 +61270,17 @@ SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor *pCur){
return pCur->eState!=CURSOR_VALID;
}
+/*
+** Return a pointer to a fake BtCursor object that will always answer
+** false to the sqlite3BtreeCursorHasMoved() routine above. The fake
+** cursor returned must not be used with any other Btree interface.
+*/
+SQLITE_PRIVATE BtCursor *sqlite3BtreeFakeValidCursor(void){
+ static u8 fakeCursor = CURSOR_VALID;
+ assert( offsetof(BtCursor, eState)==0 );
+ return (BtCursor*)&fakeCursor;
+}
+
/*
** This routine restores a cursor back to its original position after it
** has been moved by some outside activity (such as a btree rebalance or
@@ -59245,7 +61446,7 @@ static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){
if( pPgno ) *pPgno = get4byte(&pPtrmap[offset+1]);
sqlite3PagerUnref(pDbPage);
- if( *pEType<1 || *pEType>5 ) return SQLITE_CORRUPT_BKPT;
+ if( *pEType<1 || *pEType>5 ) return SQLITE_CORRUPT_PGNO(iPtrmap);
return SQLITE_OK;
}
@@ -59563,17 +61764,18 @@ static void ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell, int *pRC){
/*
-** Defragment the page given. All Cells are moved to the
-** end of the page and all free space is collected into one
-** big FreeBlk that occurs in between the header and cell
-** pointer array and the cell content area.
+** Defragment the page given. This routine reorganizes cells within the
+** page so that there are no free-blocks on the free-block list.
+**
+** Parameter nMaxFrag is the maximum amount of fragmented space that may be
+** present in the page after this routine returns.
**
** EVIDENCE-OF: R-44582-60138 SQLite may from time to time reorganize a
** b-tree page so that there are no freeblocks or fragment bytes, all
** unused bytes are contained in the unallocated space region, and all
** cells are packed tightly at the end of the page.
*/
-static int defragmentPage(MemPage *pPage){
+static int defragmentPage(MemPage *pPage, int nMaxFrag){
int i; /* Loop counter */
int pc; /* Address of the i-th cell */
int hdr; /* Offset to the page header */
@@ -59588,7 +61790,6 @@ static int defragmentPage(MemPage *pPage){
int iCellFirst; /* First allowable cell index */
int iCellLast; /* Last possible cell index */
-
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
assert( pPage->pBt!=0 );
assert( pPage->pBt->usableSize <= SQLITE_MAX_PAGE_SIZE );
@@ -59600,9 +61801,59 @@ static int defragmentPage(MemPage *pPage){
cellOffset = pPage->cellOffset;
nCell = pPage->nCell;
assert( nCell==get2byte(&data[hdr+3]) );
+ iCellFirst = cellOffset + 2*nCell;
usableSize = pPage->pBt->usableSize;
+
+ /* This block handles pages with two or fewer free blocks and nMaxFrag
+ ** or fewer fragmented bytes. In this case it is faster to move the
+ ** two (or one) blocks of cells using memmove() and add the required
+ ** offsets to each pointer in the cell-pointer array than it is to
+ ** reconstruct the entire page. */
+ if( (int)data[hdr+7]<=nMaxFrag ){
+ int iFree = get2byte(&data[hdr+1]);
+ if( iFree ){
+ int iFree2 = get2byte(&data[iFree]);
+
+ /* pageFindSlot() has already verified that free blocks are sorted
+ ** in order of offset within the page, and that no block extends
+ ** past the end of the page. Provided the two free slots do not
+ ** overlap, this guarantees that the memmove() calls below will not
+ ** overwrite the usableSize byte buffer, even if the database page
+ ** is corrupt. */
+ assert( iFree2==0 || iFree2>iFree );
+ assert( iFree+get2byte(&data[iFree+2]) <= usableSize );
+ assert( iFree2==0 || iFree2+get2byte(&data[iFree2+2]) <= usableSize );
+
+ if( 0==iFree2 || (data[iFree2]==0 && data[iFree2+1]==0) ){
+ u8 *pEnd = &data[cellOffset + nCell*2];
+ u8 *pAddr;
+ int sz2 = 0;
+ int sz = get2byte(&data[iFree+2]);
+ int top = get2byte(&data[hdr+5]);
+ if( top>=iFree ){
+ return SQLITE_CORRUPT_PAGE(pPage);
+ }
+ if( iFree2 ){
+ assert( iFree+sz<=iFree2 ); /* Verified by pageFindSlot() */
+ sz2 = get2byte(&data[iFree2+2]);
+ assert( iFree+sz+sz2+iFree2-(iFree+sz) <= usableSize );
+ memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz));
+ sz += sz2;
+ }
+ cbrk = top+sz;
+ assert( cbrk+(iFree-top) <= usableSize );
+ memmove(&data[cbrk], &data[top], iFree-top);
+ for(pAddr=&data[cellOffset]; pAddriCellLast ){
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT_PAGE(pPage);
}
assert( pc>=iCellFirst && pc<=iCellLast );
size = pPage->xCellSize(pPage, &src[pc]);
cbrk -= size;
if( cbrkusableSize ){
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT_PAGE(pPage);
}
assert( cbrk+size<=usableSize && cbrk>=iCellFirst );
testcase( cbrk+size==usableSize );
@@ -59636,16 +61887,18 @@ static int defragmentPage(MemPage *pPage){
}
memcpy(&data[cbrk], &src[pc], size);
}
+ data[hdr+7] = 0;
+
+ defragment_out:
+ if( data[hdr+7]+cbrk-iCellFirst!=pPage->nFree ){
+ return SQLITE_CORRUPT_PAGE(pPage);
+ }
assert( cbrk>=iCellFirst );
put2byte(&data[hdr+5], cbrk);
data[hdr+1] = 0;
data[hdr+2] = 0;
- data[hdr+7] = 0;
memset(&data[iCellFirst], 0, cbrk-iCellFirst);
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
- if( cbrk-iCellFirst!=pPage->nFree ){
- return SQLITE_CORRUPT_BKPT;
- }
return SQLITE_OK;
}
@@ -59670,16 +61923,10 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){
int pc = get2byte(&aData[iAddr]);
int x;
int usableSize = pPg->pBt->usableSize;
+ int size; /* Size of the free slot */
assert( pc>0 );
- do{
- int size; /* Size of the free slot */
- /* EVIDENCE-OF: R-06866-39125 Freeblocks are always connected in order of
- ** increasing offset. */
- if( pc>usableSize-4 || pc=0 ){
testcase( x==4 );
testcase( x==3 );
- if( pc < pPg->cellOffset+2*pPg->nCell || size+pc > usableSize ){
- *pRc = SQLITE_CORRUPT_BKPT;
+ if( size+pc > usableSize ){
+ *pRc = SQLITE_CORRUPT_PAGE(pPg);
return 0;
}else if( x<4 ){
/* EVIDENCE-OF: R-11498-58022 In a well-formed b-tree page, the total
@@ -59708,7 +61955,11 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){
}
iAddr = pc;
pc = get2byte(&aData[pc]);
- }while( pc );
+ if( pcpBt->usableSize==65536 ){
top = 65536;
}else{
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT_PAGE(pPage);
}
}
@@ -59783,10 +62034,10 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
testcase( gap+2+nByte==top );
if( gap+2+nByte>top ){
assert( pPage->nCell>0 || CORRUPT_DB );
- rc = defragmentPage(pPage);
+ rc = defragmentPage(pPage, MIN(4, pPage->nFree - (2+nByte)));
if( rc ) return rc;
top = get2byteNotZero(&data[hdr+5]);
- assert( gap+nByte<=top );
+ assert( gap+2+nByte<=top );
}
@@ -59822,7 +62073,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
u8 hdr; /* Page header size. 0 or 100 */
u8 nFrag = 0; /* Reduction in fragmentation */
u16 iOrigSize = iSize; /* Original value of iSize */
- u32 iLast = pPage->pBt->usableSize-4; /* Largest possible freeblock offset */
+ u16 x; /* Offset to cell content area */
u32 iEnd = iStart + iSize; /* First byte past the iStart buffer */
unsigned char *data = pPage->aData; /* Page content */
@@ -59832,13 +62083,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
assert( CORRUPT_DB || iEnd <= pPage->pBt->usableSize );
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
assert( iSize>=4 ); /* Minimum cell size is 4 */
- assert( iStart<=iLast );
-
- /* Overwrite deleted information with zeros when the secure_delete
- ** option is enabled */
- if( pPage->pBt->btsFlags & BTS_SECURE_DELETE ){
- memset(&data[iStart], 0, iSize);
- }
+ assert( iStart<=pPage->pBt->usableSize-4 );
/* The list of freeblocks must be in ascending order. Find the
** spot on the list where iStart should be inserted.
@@ -59851,11 +62096,13 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
while( (iFreeBlk = get2byte(&data[iPtr]))iLast ) return SQLITE_CORRUPT_BKPT;
+ if( iFreeBlk>pPage->pBt->usableSize-4 ){
+ return SQLITE_CORRUPT_PAGE(pPage);
+ }
assert( iFreeBlk>iPtr || iFreeBlk==0 );
/* At this point:
@@ -59866,9 +62113,11 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
*/
if( iFreeBlk && iEnd+3>=iFreeBlk ){
nFrag = iFreeBlk - iEnd;
- if( iEnd>iFreeBlk ) return SQLITE_CORRUPT_BKPT;
+ if( iEnd>iFreeBlk ) return SQLITE_CORRUPT_PAGE(pPage);
iEnd = iFreeBlk + get2byte(&data[iFreeBlk+2]);
- if( iEnd > pPage->pBt->usableSize ) return SQLITE_CORRUPT_BKPT;
+ if( iEnd > pPage->pBt->usableSize ){
+ return SQLITE_CORRUPT_PAGE(pPage);
+ }
iSize = iEnd - iStart;
iFreeBlk = get2byte(&data[iFreeBlk]);
}
@@ -59880,28 +62129,34 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
if( iPtr>hdr+1 ){
int iPtrEnd = iPtr + get2byte(&data[iPtr+2]);
if( iPtrEnd+3>=iStart ){
- if( iPtrEnd>iStart ) return SQLITE_CORRUPT_BKPT;
+ if( iPtrEnd>iStart ) return SQLITE_CORRUPT_PAGE(pPage);
nFrag += iStart - iPtrEnd;
iSize = iEnd - iPtr;
iStart = iPtr;
}
}
- if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_BKPT;
+ if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_PAGE(pPage);
data[hdr+7] -= nFrag;
}
- if( iStart==get2byte(&data[hdr+5]) ){
+ x = get2byte(&data[hdr+5]);
+ if( iStart<=x ){
/* The new freeblock is at the beginning of the cell content area,
** so just extend the cell content area rather than create another
** freelist entry */
- if( iPtr!=hdr+1 ) return SQLITE_CORRUPT_BKPT;
+ if( iStartpBt->btsFlags & BTS_FAST_SECURE ){
+ /* Overwrite deleted information with zeros when the secure_delete
+ ** option is enabled */
+ memset(&data[iStart], 0, iSize);
+ }
+ put2byte(&data[iStart], iFreeBlk);
+ put2byte(&data[iStart+2], iSize);
pPage->nFree += iOrigSize;
return SQLITE_OK;
}
@@ -59961,7 +62216,7 @@ static int decodeFlags(MemPage *pPage, int flagByte){
}else{
/* EVIDENCE-OF: R-47608-56469 Any other value for the b-tree page type is
** an error. */
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT_PAGE(pPage);
}
pPage->max1bytePayload = pBt->max1bytePayload;
return SQLITE_OK;
@@ -59977,6 +62232,16 @@ static int decodeFlags(MemPage *pPage, int flagByte){
** we failed to detect any corruption.
*/
static int btreeInitPage(MemPage *pPage){
+ int pc; /* Address of a freeblock within pPage->aData[] */
+ u8 hdr; /* Offset to beginning of page header */
+ u8 *data; /* Equal to pPage->aData */
+ BtShared *pBt; /* The main btree structure */
+ int usableSize; /* Amount of usable space on each page */
+ u16 cellOffset; /* Offset from start of page to first cell pointer */
+ int nFree; /* Number of unused bytes on the page */
+ int top; /* First byte of the cell content area */
+ int iCellFirst; /* First allowable cell or freeblock offset */
+ int iCellLast; /* Last possible cell or freeblock offset */
assert( pPage->pBt!=0 );
assert( pPage->pBt->db!=0 );
@@ -59984,122 +62249,119 @@ static int btreeInitPage(MemPage *pPage){
assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) );
assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) );
assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) );
+ assert( pPage->isInit==0 );
- if( !pPage->isInit ){
- u16 pc; /* Address of a freeblock within pPage->aData[] */
- u8 hdr; /* Offset to beginning of page header */
- u8 *data; /* Equal to pPage->aData */
- BtShared *pBt; /* The main btree structure */
- int usableSize; /* Amount of usable space on each page */
- u16 cellOffset; /* Offset from start of page to first cell pointer */
- int nFree; /* Number of unused bytes on the page */
- int top; /* First byte of the cell content area */
- int iCellFirst; /* First allowable cell or freeblock offset */
- int iCellLast; /* Last possible cell or freeblock offset */
-
- pBt = pPage->pBt;
-
- hdr = pPage->hdrOffset;
- data = pPage->aData;
- /* EVIDENCE-OF: R-28594-02890 The one-byte flag at offset 0 indicating
- ** the b-tree page type. */
- if( decodeFlags(pPage, data[hdr]) ) return SQLITE_CORRUPT_BKPT;
- assert( pBt->pageSize>=512 && pBt->pageSize<=65536 );
- pPage->maskPage = (u16)(pBt->pageSize - 1);
- pPage->nOverflow = 0;
- usableSize = pBt->usableSize;
- pPage->cellOffset = cellOffset = hdr + 8 + pPage->childPtrSize;
- pPage->aDataEnd = &data[usableSize];
- pPage->aCellIdx = &data[cellOffset];
- pPage->aDataOfst = &data[pPage->childPtrSize];
- /* EVIDENCE-OF: R-58015-48175 The two-byte integer at offset 5 designates
- ** the start of the cell content area. A zero value for this integer is
- ** interpreted as 65536. */
- top = get2byteNotZero(&data[hdr+5]);
- /* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the
- ** number of cells on the page. */
- pPage->nCell = get2byte(&data[hdr+3]);
- if( pPage->nCell>MX_CELL(pBt) ){
- /* To many cells for a single page. The page must be corrupt */
- return SQLITE_CORRUPT_BKPT;
+ pBt = pPage->pBt;
+ hdr = pPage->hdrOffset;
+ data = pPage->aData;
+ /* EVIDENCE-OF: R-28594-02890 The one-byte flag at offset 0 indicating
+ ** the b-tree page type. */
+ if( decodeFlags(pPage, data[hdr]) ){
+ return SQLITE_CORRUPT_PAGE(pPage);
+ }
+ assert( pBt->pageSize>=512 && pBt->pageSize<=65536 );
+ pPage->maskPage = (u16)(pBt->pageSize - 1);
+ pPage->nOverflow = 0;
+ usableSize = pBt->usableSize;
+ pPage->cellOffset = cellOffset = hdr + 8 + pPage->childPtrSize;
+ pPage->aDataEnd = &data[usableSize];
+ pPage->aCellIdx = &data[cellOffset];
+ pPage->aDataOfst = &data[pPage->childPtrSize];
+ /* EVIDENCE-OF: R-58015-48175 The two-byte integer at offset 5 designates
+ ** the start of the cell content area. A zero value for this integer is
+ ** interpreted as 65536. */
+ top = get2byteNotZero(&data[hdr+5]);
+ /* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the
+ ** number of cells on the page. */
+ pPage->nCell = get2byte(&data[hdr+3]);
+ if( pPage->nCell>MX_CELL(pBt) ){
+ /* To many cells for a single page. The page must be corrupt */
+ return SQLITE_CORRUPT_PAGE(pPage);
+ }
+ testcase( pPage->nCell==MX_CELL(pBt) );
+ /* EVIDENCE-OF: R-24089-57979 If a page contains no cells (which is only
+ ** possible for a root page of a table that contains no rows) then the
+ ** offset to the cell content area will equal the page size minus the
+ ** bytes of reserved space. */
+ assert( pPage->nCell>0 || top==usableSize || CORRUPT_DB );
+
+ /* A malformed database page might cause us to read past the end
+ ** of page when parsing a cell.
+ **
+ ** The following block of code checks early to see if a cell extends
+ ** past the end of a page boundary and causes SQLITE_CORRUPT to be
+ ** returned if it does.
+ */
+ iCellFirst = cellOffset + 2*pPage->nCell;
+ iCellLast = usableSize - 4;
+ if( pBt->db->flags & SQLITE_CellSizeCk ){
+ int i; /* Index into the cell pointer array */
+ int sz; /* Size of a cell */
+
+ if( !pPage->leaf ) iCellLast--;
+ for(i=0; inCell; i++){
+ pc = get2byteAligned(&data[cellOffset+i*2]);
+ testcase( pc==iCellFirst );
+ testcase( pc==iCellLast );
+ if( pciCellLast ){
+ return SQLITE_CORRUPT_PAGE(pPage);
+ }
+ sz = pPage->xCellSize(pPage, &data[pc]);
+ testcase( pc+sz==usableSize );
+ if( pc+sz>usableSize ){
+ return SQLITE_CORRUPT_PAGE(pPage);
+ }
}
- testcase( pPage->nCell==MX_CELL(pBt) );
- /* EVIDENCE-OF: R-24089-57979 If a page contains no cells (which is only
- ** possible for a root page of a table that contains no rows) then the
- ** offset to the cell content area will equal the page size minus the
- ** bytes of reserved space. */
- assert( pPage->nCell>0 || top==usableSize || CORRUPT_DB );
-
- /* A malformed database page might cause us to read past the end
- ** of page when parsing a cell.
- **
- ** The following block of code checks early to see if a cell extends
- ** past the end of a page boundary and causes SQLITE_CORRUPT to be
- ** returned if it does.
- */
- iCellFirst = cellOffset + 2*pPage->nCell;
- iCellLast = usableSize - 4;
- if( pBt->db->flags & SQLITE_CellSizeCk ){
- int i; /* Index into the cell pointer array */
- int sz; /* Size of a cell */
-
- if( !pPage->leaf ) iCellLast--;
- for(i=0; inCell; i++){
- pc = get2byteAligned(&data[cellOffset+i*2]);
- testcase( pc==iCellFirst );
- testcase( pc==iCellLast );
- if( pciCellLast ){
- return SQLITE_CORRUPT_BKPT;
- }
- sz = pPage->xCellSize(pPage, &data[pc]);
- testcase( pc+sz==usableSize );
- if( pc+sz>usableSize ){
- return SQLITE_CORRUPT_BKPT;
- }
- }
- if( !pPage->leaf ) iCellLast++;
- }
+ if( !pPage->leaf ) iCellLast++;
+ }
- /* Compute the total free space on the page
- ** EVIDENCE-OF: R-23588-34450 The two-byte integer at offset 1 gives the
- ** start of the first freeblock on the page, or is zero if there are no
- ** freeblocks. */
- pc = get2byte(&data[hdr+1]);
- nFree = data[hdr+7] + top; /* Init nFree to non-freeblock free space */
- while( pc>0 ){
- u16 next, size;
- if( pciCellLast ){
- /* EVIDENCE-OF: R-55530-52930 In a well-formed b-tree page, there will
- ** always be at least one cell before the first freeblock.
- **
- ** Or, the freeblock is off the end of the page
- */
- return SQLITE_CORRUPT_BKPT;
+ /* Compute the total free space on the page
+ ** EVIDENCE-OF: R-23588-34450 The two-byte integer at offset 1 gives the
+ ** start of the first freeblock on the page, or is zero if there are no
+ ** freeblocks. */
+ pc = get2byte(&data[hdr+1]);
+ nFree = data[hdr+7] + top; /* Init nFree to non-freeblock free space */
+ if( pc>0 ){
+ u32 next, size;
+ if( pciCellLast ){
+ /* Freeblock off the end of the page */
+ return SQLITE_CORRUPT_PAGE(pPage);
}
next = get2byte(&data[pc]);
size = get2byte(&data[pc+2]);
- if( (next>0 && next<=pc+size+3) || pc+size>usableSize ){
- /* Free blocks must be in ascending order. And the last byte of
- ** the free-block must lie on the database page. */
- return SQLITE_CORRUPT_BKPT;
- }
nFree = nFree + size;
+ if( next<=pc+size+3 ) break;
pc = next;
}
-
- /* At this point, nFree contains the sum of the offset to the start
- ** of the cell-content area plus the number of free bytes within
- ** the cell-content area. If this is greater than the usable-size
- ** of the page, then the page must be corrupted. This check also
- ** serves to verify that the offset to the start of the cell-content
- ** area, according to the page header, lies within the page.
- */
- if( nFree>usableSize ){
- return SQLITE_CORRUPT_BKPT;
+ if( next>0 ){
+ /* Freeblock not in ascending order */
+ return SQLITE_CORRUPT_PAGE(pPage);
}
- pPage->nFree = (u16)(nFree - iCellFirst);
- pPage->isInit = 1;
+ if( pc+size>(unsigned int)usableSize ){
+ /* Last freeblock extends past page end */
+ return SQLITE_CORRUPT_PAGE(pPage);
+ }
+ }
+
+ /* At this point, nFree contains the sum of the offset to the start
+ ** of the cell-content area plus the number of free bytes within
+ ** the cell-content area. If this is greater than the usable-size
+ ** of the page, then the page must be corrupted. This check also
+ ** serves to verify that the offset to the start of the cell-content
+ ** area, according to the page header, lies within the page.
+ */
+ if( nFree>usableSize ){
+ return SQLITE_CORRUPT_PAGE(pPage);
}
+ pPage->nFree = (u16)(nFree - iCellFirst);
+ pPage->isInit = 1;
return SQLITE_OK;
}
@@ -60118,7 +62380,7 @@ static void zeroPage(MemPage *pPage, int flags){
assert( sqlite3PagerGetData(pPage->pDbPage) == data );
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
assert( sqlite3_mutex_held(pBt->mutex) );
- if( pBt->btsFlags & BTS_SECURE_DELETE ){
+ if( pBt->btsFlags & BTS_FAST_SECURE ){
memset(&data[hdr], 0, pBt->usableSize - hdr);
}
data[hdr] = (char)flags;
@@ -60209,7 +62471,7 @@ static Pgno btreePagecount(BtShared *pBt){
}
SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree *p){
assert( sqlite3BtreeHoldsMutex(p) );
- assert( ((p->pBt->nPage)&0x8000000)==0 );
+ assert( ((p->pBt->nPage)&0x80000000)==0 );
return btreePagecount(p->pBt);
}
@@ -60236,7 +62498,7 @@ static int getAndInitPage(
int rc;
DbPage *pDbPage;
assert( sqlite3_mutex_held(pBt->mutex) );
- assert( pCur==0 || ppPage==&pCur->apPage[pCur->iPage] );
+ assert( pCur==0 || ppPage==&pCur->pPage );
assert( pCur==0 || bReadOnly==pCur->curPagerFlags );
assert( pCur==0 || pCur->iPage>0 );
@@ -60263,14 +62525,17 @@ static int getAndInitPage(
/* If obtaining a child page for a cursor, we must verify that the page is
** compatible with the root page. */
if( pCur && ((*ppPage)->nCell<1 || (*ppPage)->intKey!=pCur->curIntKey) ){
- rc = SQLITE_CORRUPT_BKPT;
+ rc = SQLITE_CORRUPT_PGNO(pgno);
releasePage(*ppPage);
goto getAndInitPage_error;
}
return SQLITE_OK;
getAndInitPage_error:
- if( pCur ) pCur->iPage--;
+ if( pCur ){
+ pCur->iPage--;
+ pCur->pPage = pCur->apPage[pCur->iPage];
+ }
testcase( pgno==0 );
assert( pgno!=0 || rc==SQLITE_CORRUPT );
return rc;
@@ -60279,6 +62544,8 @@ static int getAndInitPage(
/*
** Release a MemPage. This should be called once for each prior
** call to btreeGetPage.
+**
+** Page1 is a special case and must be released using releasePageOne().
*/
static void releasePageNotNull(MemPage *pPage){
assert( pPage->aData );
@@ -60292,6 +62559,16 @@ static void releasePageNotNull(MemPage *pPage){
static void releasePage(MemPage *pPage){
if( pPage ) releasePageNotNull(pPage);
}
+static void releasePageOne(MemPage *pPage){
+ assert( pPage!=0 );
+ assert( pPage->aData );
+ assert( pPage->pBt );
+ assert( pPage->pDbPage!=0 );
+ assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage );
+ assert( sqlite3PagerGetData(pPage->pDbPage)==pPage->aData );
+ assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+ sqlite3PagerUnrefPageOne(pPage->pDbPage);
+}
/*
** Get an unused page.
@@ -60525,7 +62802,7 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
goto btree_open_out;
}
rc = sqlite3PagerOpen(pVfs, &pBt->pPager, zFilename,
- EXTRA_SIZE, flags, vfsFlags, pageReinit);
+ sizeof(MemPage), flags, vfsFlags, pageReinit);
if( rc==SQLITE_OK ){
sqlite3PagerSetMmapLimit(pBt->pPager, db->szMmap);
rc = sqlite3PagerReadFileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader);
@@ -60541,8 +62818,10 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
pBt->pCursor = 0;
pBt->pPage1 = 0;
if( sqlite3PagerIsreadonly(pBt->pPager) ) pBt->btsFlags |= BTS_READ_ONLY;
-#ifdef SQLITE_SECURE_DELETE
+#if defined(SQLITE_SECURE_DELETE)
pBt->btsFlags |= BTS_SECURE_DELETE;
+#elif defined(SQLITE_FAST_SECURE_DELETE)
+ pBt->btsFlags |= BTS_OVERWRITE;
#endif
/* EVIDENCE-OF: R-51873-39618 The page size for a database file is
** determined by the 2-byte integer located at an offset of 16 bytes from
@@ -60638,12 +62917,14 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
btree_open_out:
if( rc!=SQLITE_OK ){
if( pBt && pBt->pPager ){
- sqlite3PagerClose(pBt->pPager);
+ sqlite3PagerClose(pBt->pPager, 0);
}
sqlite3_free(pBt);
sqlite3_free(p);
*ppBtree = 0;
}else{
+ sqlite3_file *pFile;
+
/* If the B-Tree was successfully opened, set the pager-cache size to the
** default value. Except, when opening on an existing shared pager-cache,
** do not change the pager-cache size.
@@ -60651,6 +62932,11 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
if( sqlite3BtreeSchema(p, 0, 0)==0 ){
sqlite3PagerSetCachesize(p->pBt->pPager, SQLITE_DEFAULT_CACHE_SIZE);
}
+
+ pFile = sqlite3PagerFile(pBt->pPager);
+ if( pFile->pMethods ){
+ sqlite3OsFileControlHint(pFile, SQLITE_FCNTL_PDB, (void*)&pBt->db);
+ }
}
if( mutexOpen ){
assert( sqlite3_mutex_held(mutexOpen) );
@@ -60780,7 +63066,7 @@ SQLITE_PRIVATE int sqlite3BtreeClose(Btree *p){
** Clean out and delete the BtShared object.
*/
assert( !pBt->pCursor );
- sqlite3PagerClose(pBt->pPager);
+ sqlite3PagerClose(pBt->pPager, p->db);
if( pBt->xFreeSchema && pBt->pSchema ){
pBt->xFreeSchema(pBt->pSchema);
}
@@ -60983,19 +63269,34 @@ SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree *p, int mxPage){
}
/*
-** Set the BTS_SECURE_DELETE flag if newFlag is 0 or 1. If newFlag is -1,
-** then make no changes. Always return the value of the BTS_SECURE_DELETE
-** setting after the change.
+** Change the values for the BTS_SECURE_DELETE and BTS_OVERWRITE flags:
+**
+** newFlag==0 Both BTS_SECURE_DELETE and BTS_OVERWRITE are cleared
+** newFlag==1 BTS_SECURE_DELETE set and BTS_OVERWRITE is cleared
+** newFlag==2 BTS_SECURE_DELETE cleared and BTS_OVERWRITE is set
+** newFlag==(-1) No changes
+**
+** This routine acts as a query if newFlag is less than zero
+**
+** With BTS_OVERWRITE set, deleted content is overwritten by zeros, but
+** freelist leaf pages are not written back to the database. Thus in-page
+** deleted content is cleared, but freelist deleted content is not.
+**
+** With BTS_SECURE_DELETE, operation is like BTS_OVERWRITE with the addition
+** that freelist leaf pages are written back into the database, increasing
+** the amount of disk I/O.
*/
SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree *p, int newFlag){
int b;
if( p==0 ) return 0;
sqlite3BtreeEnter(p);
+ assert( BTS_OVERWRITE==BTS_SECURE_DELETE*2 );
+ assert( BTS_FAST_SECURE==(BTS_OVERWRITE|BTS_SECURE_DELETE) );
if( newFlag>=0 ){
- p->pBt->btsFlags &= ~BTS_SECURE_DELETE;
- if( newFlag ) p->pBt->btsFlags |= BTS_SECURE_DELETE;
- }
- b = (p->pBt->btsFlags & BTS_SECURE_DELETE)!=0;
+ p->pBt->btsFlags &= ~BTS_FAST_SECURE;
+ p->pBt->btsFlags |= BTS_SECURE_DELETE*newFlag;
+ }
+ b = (p->pBt->btsFlags & BTS_FAST_SECURE)/BTS_SECURE_DELETE;
sqlite3BtreeLeave(p);
return b;
}
@@ -61046,6 +63347,32 @@ SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *p){
#endif
}
+/*
+** If the user has not set the safety-level for this database connection
+** using "PRAGMA synchronous", and if the safety-level is not already
+** set to the value passed to this function as the second parameter,
+** set it so.
+*/
+#if SQLITE_DEFAULT_SYNCHRONOUS!=SQLITE_DEFAULT_WAL_SYNCHRONOUS \
+ && !defined(SQLITE_OMIT_WAL)
+static void setDefaultSyncFlag(BtShared *pBt, u8 safety_level){
+ sqlite3 *db;
+ Db *pDb;
+ if( (db=pBt->db)!=0 && (pDb=db->aDb)!=0 ){
+ while( pDb->pBt==0 || pDb->pBt->pBt!=pBt ){ pDb++; }
+ if( pDb->bSyncSet==0
+ && pDb->safety_level!=safety_level
+ && pDb!=&db->aDb[1]
+ ){
+ pDb->safety_level = safety_level;
+ sqlite3PagerSetFlags(pBt->pPager,
+ pDb->safety_level | (db->flags & PAGER_FLAGS_MASK));
+ }
+ }
+}
+#else
+# define setDefaultSyncFlag(pBt,safety_level)
+#endif
/*
** Get a reference to pPage1 of the database file. This will
@@ -61119,26 +63446,15 @@ static int lockBtree(BtShared *pBt){
if( rc!=SQLITE_OK ){
goto page1_init_failed;
}else{
-#if SQLITE_DEFAULT_SYNCHRONOUS!=SQLITE_DEFAULT_WAL_SYNCHRONOUS
- sqlite3 *db;
- Db *pDb;
- if( (db=pBt->db)!=0 && (pDb=db->aDb)!=0 ){
- while( pDb->pBt==0 || pDb->pBt->pBt!=pBt ){ pDb++; }
- if( pDb->bSyncSet==0
- && pDb->safety_level==SQLITE_DEFAULT_SYNCHRONOUS+1
- ){
- pDb->safety_level = SQLITE_DEFAULT_WAL_SYNCHRONOUS+1;
- sqlite3PagerSetFlags(pBt->pPager,
- pDb->safety_level | (db->flags & PAGER_FLAGS_MASK));
- }
- }
-#endif
+ setDefaultSyncFlag(pBt, SQLITE_DEFAULT_WAL_SYNCHRONOUS+1);
if( isOpen==0 ){
- releasePage(pPage1);
+ releasePageOne(pPage1);
return SQLITE_OK;
}
}
rc = SQLITE_NOTADB;
+ }else{
+ setDefaultSyncFlag(pBt, SQLITE_DEFAULT_SYNCHRONOUS+1);
}
#endif
@@ -61179,7 +63495,7 @@ static int lockBtree(BtShared *pBt){
** zero and return SQLITE_OK. The caller will call this function
** again with the correct page-size.
*/
- releasePage(pPage1);
+ releasePageOne(pPage1);
pBt->usableSize = usableSize;
pBt->pageSize = pageSize;
freeTempSpace(pBt);
@@ -61187,7 +63503,7 @@ static int lockBtree(BtShared *pBt){
pageSize-usableSize);
return rc;
}
- if( (pBt->db->flags & SQLITE_RecoveryMode)==0 && nPage>nPageFile ){
+ if( (pBt->db->flags & SQLITE_WriteSchema)==0 && nPage>nPageFile ){
rc = SQLITE_CORRUPT_BKPT;
goto page1_init_failed;
}
@@ -61233,7 +63549,7 @@ static int lockBtree(BtShared *pBt){
return SQLITE_OK;
page1_init_failed:
- releasePage(pPage1);
+ releasePageOne(pPage1);
pBt->pPage1 = 0;
return rc;
}
@@ -61278,7 +63594,7 @@ static void unlockBtreeIfUnused(BtShared *pBt){
assert( pPage1->aData );
assert( sqlite3PagerRefcount(pBt->pPager)==1 );
pBt->pPage1 = 0;
- releasePageNotNull(pPage1);
+ releasePageOne(pPage1);
}
}
@@ -61527,14 +63843,11 @@ static int setChildPtrmaps(MemPage *pPage){
int nCell; /* Number of cells in page pPage */
int rc; /* Return code */
BtShared *pBt = pPage->pBt;
- u8 isInitOrig = pPage->isInit;
Pgno pgno = pPage->pgno;
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- rc = btreeInitPage(pPage);
- if( rc!=SQLITE_OK ){
- goto set_child_ptrmaps_out;
- }
+ rc = pPage->isInit ? SQLITE_OK : btreeInitPage(pPage);
+ if( rc!=SQLITE_OK ) return rc;
nCell = pPage->nCell;
for(i=0; iisInit = isInitOrig;
return rc;
}
@@ -61578,16 +63889,15 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
if( eType==PTRMAP_OVERFLOW2 ){
/* The pointer is always the first 4 bytes of the page in this case. */
if( get4byte(pPage->aData)!=iFrom ){
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT_PAGE(pPage);
}
put4byte(pPage->aData, iTo);
}else{
- u8 isInitOrig = pPage->isInit;
int i;
int nCell;
int rc;
- rc = btreeInitPage(pPage);
+ rc = pPage->isInit ? SQLITE_OK : btreeInitPage(pPage);
if( rc ) return rc;
nCell = pPage->nCell;
@@ -61596,12 +63906,14 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
if( eType==PTRMAP_OVERFLOW1 ){
CellInfo info;
pPage->xParseCell(pPage, pCell, &info);
- if( info.nLocalaData+pPage->maskPage
- && iFrom==get4byte(pCell+info.nSize-4)
- ){
- put4byte(pCell+info.nSize-4, iTo);
- break;
+ if( info.nLocal pPage->aData+pPage->pBt->usableSize ){
+ return SQLITE_CORRUPT_PAGE(pPage);
+ }
+ if( iFrom==get4byte(pCell+info.nSize-4) ){
+ put4byte(pCell+info.nSize-4, iTo);
+ break;
+ }
}
}else{
if( get4byte(pCell)==iFrom ){
@@ -61614,12 +63926,10 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
if( i==nCell ){
if( eType!=PTRMAP_BTREE ||
get4byte(&pPage->aData[pPage->hdrOffset+8])!=iFrom ){
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT_PAGE(pPage);
}
put4byte(&pPage->aData[pPage->hdrOffset+8], iTo);
}
-
- pPage->isInit = isInitOrig;
}
return SQLITE_OK;
}
@@ -62136,7 +64446,6 @@ SQLITE_PRIVATE int sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode, int wr
if( pBtree ){
sqlite3BtreeEnter(pBtree);
for(p=pBtree->pBt->pCursor; p; p=p->pNext){
- int i;
if( writeOnly && (p->curFlags & BTCF_WriteFlag)==0 ){
if( p->eState==CURSOR_VALID || p->eState==CURSOR_SKIPNEXT ){
rc = saveCursorPosition(p);
@@ -62150,10 +64459,7 @@ SQLITE_PRIVATE int sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode, int wr
p->eState = CURSOR_FAULT;
p->skipNext = errCode;
}
- for(i=0; i<=p->iPage; i++){
- releasePage(p->apPage[i]);
- p->apPage[i] = 0;
- }
+ btreeReleaseAllCursorPages(p);
}
sqlite3BtreeLeave(pBtree);
}
@@ -62210,7 +64516,7 @@ SQLITE_PRIVATE int sqlite3BtreeRollback(Btree *p, int tripCode, int writeOnly){
if( nPage==0 ) sqlite3PagerPagecount(pBt->pPager, &nPage);
testcase( pBt->nPage!=nPage );
pBt->nPage = nPage;
- releasePage(pPage1);
+ releasePageOne(pPage1);
}
assert( countValidCursors(pBt, 1)==0 );
pBt->inTransaction = TRANS_READ;
@@ -62278,7 +64584,12 @@ SQLITE_PRIVATE int sqlite3BtreeSavepoint(Btree *p, int op, int iSavepoint){
assert( op==SAVEPOINT_RELEASE || op==SAVEPOINT_ROLLBACK );
assert( iSavepoint>=0 || (iSavepoint==-1 && op==SAVEPOINT_ROLLBACK) );
sqlite3BtreeEnter(p);
- rc = sqlite3PagerSavepoint(pBt->pPager, op, iSavepoint);
+ if( op==SAVEPOINT_ROLLBACK ){
+ rc = saveAllCursors(pBt, 0, 0);
+ }
+ if( rc==SQLITE_OK ){
+ rc = sqlite3PagerSavepoint(pBt->pPager, op, iSavepoint);
+ }
if( rc==SQLITE_OK ){
if( iSavepoint<0 && (pBt->btsFlags & BTS_INITIALLY_EMPTY)!=0 ){
pBt->nPage = 0;
@@ -62447,10 +64758,8 @@ SQLITE_PRIVATE void sqlite3BtreeCursorZero(BtCursor *p){
SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor *pCur){
Btree *pBtree = pCur->pBtree;
if( pBtree ){
- int i;
BtShared *pBt = pCur->pBt;
sqlite3BtreeEnter(pBtree);
- sqlite3BtreeClearCursor(pCur);
assert( pBt->pCursor!=0 );
if( pBt->pCursor==pCur ){
pBt->pCursor = pCur->pNext;
@@ -62464,12 +64773,10 @@ SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor *pCur){
pPrev = pPrev->pNext;
}while( ALWAYS(pPrev) );
}
- for(i=0; i<=pCur->iPage; i++){
- releasePage(pCur->apPage[i]);
- }
+ btreeReleaseAllCursorPages(pCur);
unlockBtreeIfUnused(pBt);
sqlite3_free(pCur->aOverflow);
- /* sqlite3_free(pCur); */
+ sqlite3_free(pCur->pKey);
sqlite3BtreeLeave(pBtree);
}
return SQLITE_OK;
@@ -62486,9 +64793,8 @@ SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor *pCur){
#ifndef NDEBUG
static void assertCellInfo(BtCursor *pCur){
CellInfo info;
- int iPage = pCur->iPage;
memset(&info, 0, sizeof(info));
- btreeParseCell(pCur->apPage[iPage], pCur->aiIdx[iPage], &info);
+ btreeParseCell(pCur->pPage, pCur->ix, &info);
assert( CORRUPT_DB || memcmp(&info, &pCur->info, sizeof(info))==0 );
}
#else
@@ -62496,9 +64802,8 @@ SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor *pCur){
#endif
static SQLITE_NOINLINE void getCellInfo(BtCursor *pCur){
if( pCur->info.nSize==0 ){
- int iPage = pCur->iPage;
pCur->curFlags |= BTCF_ValidNKey;
- btreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info);
+ btreeParseCell(pCur->pPage,pCur->ix,&pCur->info);
}else{
assertCellInfo(pCur);
}
@@ -62514,6 +64819,10 @@ SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor *pCur){
return pCur && pCur->eState==CURSOR_VALID;
}
#endif /* NDEBUG */
+SQLITE_PRIVATE int sqlite3BtreeCursorIsValidNN(BtCursor *pCur){
+ assert( pCur!=0 );
+ return pCur->eState==CURSOR_VALID;
+}
/*
** Return the value of the integer key or "rowid" for a table btree.
@@ -62529,6 +64838,20 @@ SQLITE_PRIVATE i64 sqlite3BtreeIntegerKey(BtCursor *pCur){
return pCur->info.nKey;
}
+#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
+/*
+** Return the offset into the database file for the start of the
+** payload to which the cursor is pointing.
+*/
+SQLITE_PRIVATE i64 sqlite3BtreeOffset(BtCursor *pCur){
+ assert( cursorHoldsMutex(pCur) );
+ assert( pCur->eState==CURSOR_VALID );
+ getCellInfo(pCur);
+ return (i64)pCur->pBt->pageSize*((i64)pCur->pPage->pgno - 1) +
+ (i64)(pCur->info.pPayload - pCur->pPage->aData);
+}
+#endif /* SQLITE_ENABLE_OFFSET_SQL_FUNC */
+
/*
** Return the number of bytes of payload for the entry that pCur is
** currently pointing to. For table btrees, this will be the amount
@@ -62660,7 +64983,6 @@ static int copyPayload(
**
** 0: The operation is a read. Populate the overflow cache.
** 1: The operation is a write. Populate the overflow cache.
-** 2: The operation is a read. Do not populate the overflow cache.
**
** A total of "amt" bytes are read or written beginning at "offset".
** Data is read to or from the buffer pBuf.
@@ -62668,13 +64990,13 @@ static int copyPayload(
** The content being read or written might appear on the main page
** or be scattered out on multiple overflow pages.
**
-** If the current cursor entry uses one or more overflow pages and the
-** eOp argument is not 2, this function may allocate space for and lazily
-** populates the overflow page-list cache array (BtCursor.aOverflow).
+** If the current cursor entry uses one or more overflow pages
+** this function may allocate space for and lazily populate
+** the overflow page-list cache array (BtCursor.aOverflow).
** Subsequent calls use this cache to make seeking to the supplied offset
** more efficient.
**
-** Once an overflow page-list cache has been allocated, it may be
+** Once an overflow page-list cache has been allocated, it must be
** invalidated if some other cursor writes to the same table, or if
** the cursor is moved to a different row. Additionally, in auto-vacuum
** mode, the following events may invalidate an overflow page-list cache.
@@ -62693,24 +65015,20 @@ static int accessPayload(
unsigned char *aPayload;
int rc = SQLITE_OK;
int iIdx = 0;
- MemPage *pPage = pCur->apPage[pCur->iPage]; /* Btree page of current entry */
+ MemPage *pPage = pCur->pPage; /* Btree page of current entry */
BtShared *pBt = pCur->pBt; /* Btree this cursor belongs to */
#ifdef SQLITE_DIRECT_OVERFLOW_READ
- unsigned char * const pBufStart = pBuf;
- int bEnd; /* True if reading to end of data */
+ unsigned char * const pBufStart = pBuf; /* Start of original out buffer */
#endif
assert( pPage );
+ assert( eOp==0 || eOp==1 );
assert( pCur->eState==CURSOR_VALID );
- assert( pCur->aiIdx[pCur->iPage]nCell );
+ assert( pCur->ixnCell );
assert( cursorHoldsMutex(pCur) );
- assert( eOp!=2 || offset==0 ); /* Always start from beginning for eOp==2 */
getCellInfo(pCur);
aPayload = pCur->info.pPayload;
-#ifdef SQLITE_DIRECT_OVERFLOW_READ
- bEnd = offset+amt==pCur->info.nPayload;
-#endif
assert( offset+amt <= pCur->info.nPayload );
assert( aPayload > pPage->aData );
@@ -62720,7 +65038,7 @@ static int accessPayload(
** &aPayload[pCur->info.nLocal] > &pPage->aData[pBt->usableSize]
** but is recast into its current form to avoid integer overflow problems
*/
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT_PAGE(pPage);
}
/* Check if data must be read/written to/from the btree page itself. */
@@ -62729,7 +65047,7 @@ static int accessPayload(
if( a+offset>pCur->info.nLocal ){
a = pCur->info.nLocal - offset;
}
- rc = copyPayload(&aPayload[offset], pBuf, a, (eOp & 0x01), pPage->pDbPage);
+ rc = copyPayload(&aPayload[offset], pBuf, a, eOp, pPage->pDbPage);
offset = 0;
pBuf += a;
amt -= a;
@@ -62745,53 +65063,46 @@ static int accessPayload(
nextPage = get4byte(&aPayload[pCur->info.nLocal]);
/* If the BtCursor.aOverflow[] has not been allocated, allocate it now.
- ** Except, do not allocate aOverflow[] for eOp==2.
**
** The aOverflow[] array is sized at one entry for each overflow page
** in the overflow chain. The page number of the first overflow page is
** stored in aOverflow[0], etc. A value of 0 in the aOverflow[] array
** means "not yet known" (the cache is lazily populated).
*/
- if( eOp!=2 && (pCur->curFlags & BTCF_ValidOvfl)==0 ){
+ if( (pCur->curFlags & BTCF_ValidOvfl)==0 ){
int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize;
if( nOvfl>pCur->nOvflAlloc ){
Pgno *aNew = (Pgno*)sqlite3Realloc(
pCur->aOverflow, nOvfl*2*sizeof(Pgno)
);
if( aNew==0 ){
- rc = SQLITE_NOMEM_BKPT;
+ return SQLITE_NOMEM_BKPT;
}else{
pCur->nOvflAlloc = nOvfl*2;
pCur->aOverflow = aNew;
}
}
- if( rc==SQLITE_OK ){
- memset(pCur->aOverflow, 0, nOvfl*sizeof(Pgno));
- pCur->curFlags |= BTCF_ValidOvfl;
+ memset(pCur->aOverflow, 0, nOvfl*sizeof(Pgno));
+ pCur->curFlags |= BTCF_ValidOvfl;
+ }else{
+ /* If the overflow page-list cache has been allocated and the
+ ** entry for the first required overflow page is valid, skip
+ ** directly to it.
+ */
+ if( pCur->aOverflow[offset/ovflSize] ){
+ iIdx = (offset/ovflSize);
+ nextPage = pCur->aOverflow[iIdx];
+ offset = (offset%ovflSize);
}
}
- /* If the overflow page-list cache has been allocated and the
- ** entry for the first required overflow page is valid, skip
- ** directly to it.
- */
- if( (pCur->curFlags & BTCF_ValidOvfl)!=0
- && pCur->aOverflow[offset/ovflSize]
- ){
- iIdx = (offset/ovflSize);
- nextPage = pCur->aOverflow[iIdx];
- offset = (offset%ovflSize);
- }
-
- for( ; rc==SQLITE_OK && amt>0 && nextPage; iIdx++){
-
+ assert( rc==SQLITE_OK && amt>0 );
+ while( nextPage ){
/* If required, populate the overflow page-list cache. */
- if( (pCur->curFlags & BTCF_ValidOvfl)!=0 ){
- assert( pCur->aOverflow[iIdx]==0
- || pCur->aOverflow[iIdx]==nextPage
- || CORRUPT_DB );
- pCur->aOverflow[iIdx] = nextPage;
- }
+ assert( pCur->aOverflow[iIdx]==0
+ || pCur->aOverflow[iIdx]==nextPage
+ || CORRUPT_DB );
+ pCur->aOverflow[iIdx] = nextPage;
if( offset>=ovflSize ){
/* The only reason to read this page is to obtain the page
@@ -62799,11 +65110,7 @@ static int accessPayload(
** data is not required. So first try to lookup the overflow
** page-list cache, if any, then fall back to the getOverflowPage()
** function.
- **
- ** Note that the aOverflow[] array must be allocated because eOp!=2
- ** here. If eOp==2, then offset==0 and this branch is never taken.
*/
- assert( eOp!=2 );
assert( pCur->curFlags & BTCF_ValidOvfl );
assert( pCur->pBtree->db==pBt->db );
if( pCur->aOverflow[iIdx+1] ){
@@ -62817,7 +65124,7 @@ static int accessPayload(
** range of data that is being read (eOp==0) or written (eOp!=0).
*/
#ifdef SQLITE_DIRECT_OVERFLOW_READ
- sqlite3_file *fd;
+ sqlite3_file *fd; /* File from which to do direct overflow read */
#endif
int a = amt;
if( a + offset > ovflSize ){
@@ -62829,27 +65136,25 @@ static int accessPayload(
**
** 1) this is a read operation, and
** 2) data is required from the start of this overflow page, and
- ** 3) the database is file-backed, and
- ** 4) there is no open write-transaction, and
- ** 5) the database is not a WAL database,
- ** 6) all data from the page is being read.
- ** 7) at least 4 bytes have already been read into the output buffer
+ ** 3) there is no open write-transaction, and
+ ** 4) the database is file-backed, and
+ ** 5) the page is not in the WAL file
+ ** 6) at least 4 bytes have already been read into the output buffer
**
** then data can be read directly from the database file into the
** output buffer, bypassing the page-cache altogether. This speeds
** up loading large records that span many overflow pages.
*/
- if( (eOp&0x01)==0 /* (1) */
+ if( eOp==0 /* (1) */
&& offset==0 /* (2) */
- && (bEnd || a==ovflSize) /* (6) */
- && pBt->inTransaction==TRANS_READ /* (4) */
- && (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (3) */
- && 0==sqlite3PagerUseWal(pBt->pPager) /* (5) */
- && &pBuf[-4]>=pBufStart /* (7) */
+ && pBt->inTransaction==TRANS_READ /* (3) */
+ && (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (4) */
+ && 0==sqlite3PagerUseWal(pBt->pPager, nextPage) /* (5) */
+ && &pBuf[-4]>=pBufStart /* (6) */
){
u8 aSave[4];
u8 *aWrite = &pBuf[-4];
- assert( aWrite>=pBufStart ); /* hence (7) */
+ assert( aWrite>=pBufStart ); /* due to (6) */
memcpy(aSave, aWrite, 4);
rc = sqlite3OsRead(fd, aWrite, a+4, (i64)pBt->pageSize*(nextPage-1));
nextPage = get4byte(aWrite);
@@ -62860,76 +65165,86 @@ static int accessPayload(
{
DbPage *pDbPage;
rc = sqlite3PagerGet(pBt->pPager, nextPage, &pDbPage,
- ((eOp&0x01)==0 ? PAGER_GET_READONLY : 0)
+ (eOp==0 ? PAGER_GET_READONLY : 0)
);
if( rc==SQLITE_OK ){
aPayload = sqlite3PagerGetData(pDbPage);
nextPage = get4byte(aPayload);
- rc = copyPayload(&aPayload[offset+4], pBuf, a, (eOp&0x01), pDbPage);
+ rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage);
sqlite3PagerUnref(pDbPage);
offset = 0;
}
}
amt -= a;
+ if( amt==0 ) return rc;
pBuf += a;
}
+ if( rc ) break;
+ iIdx++;
}
}
if( rc==SQLITE_OK && amt>0 ){
- return SQLITE_CORRUPT_BKPT;
+ /* Overflow chain ends prematurely */
+ return SQLITE_CORRUPT_PAGE(pPage);
}
return rc;
}
/*
-** Read part of the key associated with cursor pCur. Exactly
-** "amt" bytes will be transferred into pBuf[]. The transfer
+** Read part of the payload for the row at which that cursor pCur is currently
+** pointing. "amt" bytes will be transferred into pBuf[]. The transfer
** begins at "offset".
**
-** The caller must ensure that pCur is pointing to a valid row
-** in the table.
+** pCur can be pointing to either a table or an index b-tree.
+** If pointing to a table btree, then the content section is read. If
+** pCur is pointing to an index b-tree then the key section is read.
+**
+** For sqlite3BtreePayload(), the caller must ensure that pCur is pointing
+** to a valid row in the table. For sqlite3BtreePayloadChecked(), the
+** cursor might be invalid or might need to be restored before being read.
**
** Return SQLITE_OK on success or an error code if anything goes
** wrong. An error is returned if "offset+amt" is larger than
** the available payload.
*/
-SQLITE_PRIVATE int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
+SQLITE_PRIVATE int sqlite3BtreePayload(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
assert( cursorHoldsMutex(pCur) );
assert( pCur->eState==CURSOR_VALID );
- assert( pCur->iPage>=0 && pCur->apPage[pCur->iPage] );
- assert( pCur->aiIdx[pCur->iPage]apPage[pCur->iPage]->nCell );
+ assert( pCur->iPage>=0 && pCur->pPage );
+ assert( pCur->ixpPage->nCell );
return accessPayload(pCur, offset, amt, (unsigned char*)pBuf, 0);
}
/*
-** Read part of the data associated with cursor pCur. Exactly
-** "amt" bytes will be transfered into pBuf[]. The transfer
-** begins at "offset".
-**
-** Return SQLITE_OK on success or an error code if anything goes
-** wrong. An error is returned if "offset+amt" is larger than
-** the available payload.
+** This variant of sqlite3BtreePayload() works even if the cursor has not
+** in the CURSOR_VALID state. It is only used by the sqlite3_blob_read()
+** interface.
*/
-SQLITE_PRIVATE int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
- int rc;
-
#ifndef SQLITE_OMIT_INCRBLOB
+static SQLITE_NOINLINE int accessPayloadChecked(
+ BtCursor *pCur,
+ u32 offset,
+ u32 amt,
+ void *pBuf
+){
+ int rc;
if ( pCur->eState==CURSOR_INVALID ){
return SQLITE_ABORT;
}
-#endif
-
assert( cursorOwnsBtShared(pCur) );
- rc = restoreCursorPosition(pCur);
- if( rc==SQLITE_OK ){
- assert( pCur->eState==CURSOR_VALID );
- assert( pCur->iPage>=0 && pCur->apPage[pCur->iPage] );
- assert( pCur->aiIdx[pCur->iPage]apPage[pCur->iPage]->nCell );
- rc = accessPayload(pCur, offset, amt, pBuf, 0);
+ rc = btreeRestoreCursorPosition(pCur);
+ return rc ? rc : accessPayload(pCur, offset, amt, pBuf, 0);
+}
+SQLITE_PRIVATE int sqlite3BtreePayloadChecked(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
+ if( pCur->eState==CURSOR_VALID ){
+ assert( cursorOwnsBtShared(pCur) );
+ return accessPayload(pCur, offset, amt, pBuf, 0);
+ }else{
+ return accessPayloadChecked(pCur, offset, amt, pBuf);
}
- return rc;
}
+#endif /* SQLITE_OMIT_INCRBLOB */
/*
** Return a pointer to payload information from the entry that the
@@ -62954,18 +65269,23 @@ static const void *fetchPayload(
BtCursor *pCur, /* Cursor pointing to entry to read from */
u32 *pAmt /* Write the number of available bytes here */
){
- u32 amt;
- assert( pCur!=0 && pCur->iPage>=0 && pCur->apPage[pCur->iPage]);
+ int amt;
+ assert( pCur!=0 && pCur->iPage>=0 && pCur->pPage);
assert( pCur->eState==CURSOR_VALID );
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
assert( cursorOwnsBtShared(pCur) );
- assert( pCur->aiIdx[pCur->iPage]apPage[pCur->iPage]->nCell );
+ assert( pCur->ixpPage->nCell );
assert( pCur->info.nSize>0 );
- assert( pCur->info.pPayload>pCur->apPage[pCur->iPage]->aData || CORRUPT_DB );
- assert( pCur->info.pPayloadapPage[pCur->iPage]->aDataEnd ||CORRUPT_DB);
- amt = (int)(pCur->apPage[pCur->iPage]->aDataEnd - pCur->info.pPayload);
- if( pCur->info.nLocalinfo.nLocal;
- *pAmt = amt;
+ assert( pCur->info.pPayload>pCur->pPage->aData || CORRUPT_DB );
+ assert( pCur->info.pPayloadpPage->aDataEnd ||CORRUPT_DB);
+ amt = pCur->info.nLocal;
+ if( amt>(int)(pCur->pPage->aDataEnd - pCur->info.pPayload) ){
+ /* There is too little space on the page for the expected amount
+ ** of local content. Database must be corrupt. */
+ assert( CORRUPT_DB );
+ amt = MAX(0, (int)(pCur->pPage->aDataEnd - pCur->info.pPayload));
+ }
+ *pAmt = (u32)amt;
return (void*)pCur->info.pPayload;
}
@@ -63010,13 +65330,14 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){
}
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
+ pCur->aiIdx[pCur->iPage] = pCur->ix;
+ pCur->apPage[pCur->iPage] = pCur->pPage;
+ pCur->ix = 0;
pCur->iPage++;
- pCur->aiIdx[pCur->iPage] = 0;
- return getAndInitPage(pBt, newPgno, &pCur->apPage[pCur->iPage],
- pCur, pCur->curPagerFlags);
+ return getAndInitPage(pBt, newPgno, &pCur->pPage, pCur, pCur->curPagerFlags);
}
-#if SQLITE_DEBUG
+#ifdef SQLITE_DEBUG
/*
** Page pParent is an internal (non-leaf) tree page. This function
** asserts that page number iChild is the left-child if the iIdx'th
@@ -63047,19 +65368,23 @@ static void assertParentIndex(MemPage *pParent, int iIdx, Pgno iChild){
** the largest cell index.
*/
static void moveToParent(BtCursor *pCur){
+ MemPage *pLeaf;
assert( cursorOwnsBtShared(pCur) );
assert( pCur->eState==CURSOR_VALID );
assert( pCur->iPage>0 );
- assert( pCur->apPage[pCur->iPage] );
+ assert( pCur->pPage );
assertParentIndex(
pCur->apPage[pCur->iPage-1],
pCur->aiIdx[pCur->iPage-1],
- pCur->apPage[pCur->iPage]->pgno
+ pCur->pPage->pgno
);
testcase( pCur->aiIdx[pCur->iPage-1] > pCur->apPage[pCur->iPage-1]->nCell );
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
- releasePageNotNull(pCur->apPage[pCur->iPage--]);
+ pCur->ix = pCur->aiIdx[pCur->iPage-1];
+ pLeaf = pCur->pPage;
+ pCur->pPage = pCur->apPage[--pCur->iPage];
+ releasePageNotNull(pLeaf);
}
/*
@@ -63071,9 +65396,9 @@ static void moveToParent(BtCursor *pCur){
** single child page. This can only happen with the table rooted at page 1.
**
** If the b-tree structure is empty, the cursor state is set to
-** CURSOR_INVALID. Otherwise, the cursor is set to point to the first
-** cell located on the root (or virtual root) page and the cursor state
-** is set to CURSOR_VALID.
+** CURSOR_INVALID and this routine returns SQLITE_EMPTY. Otherwise,
+** the cursor is set to point to the first cell located on the root
+** (or virtual root) page and the cursor state is set to CURSOR_VALID.
**
** If this function returns successfully, it may be assumed that the
** page-header flags indicate that the [virtual] root-page is the expected
@@ -63091,34 +65416,40 @@ static int moveToRoot(BtCursor *pCur){
assert( CURSOR_INVALID < CURSOR_REQUIRESEEK );
assert( CURSOR_VALID < CURSOR_REQUIRESEEK );
assert( CURSOR_FAULT > CURSOR_REQUIRESEEK );
- if( pCur->eState>=CURSOR_REQUIRESEEK ){
- if( pCur->eState==CURSOR_FAULT ){
- assert( pCur->skipNext!=SQLITE_OK );
- return pCur->skipNext;
- }
- sqlite3BtreeClearCursor(pCur);
- }
+ assert( pCur->eState < CURSOR_REQUIRESEEK || pCur->iPage<0 );
+ assert( pCur->pgnoRoot>0 || pCur->iPage<0 );
if( pCur->iPage>=0 ){
- while( pCur->iPage ){
- assert( pCur->apPage[pCur->iPage]!=0 );
- releasePageNotNull(pCur->apPage[pCur->iPage--]);
+ if( pCur->iPage ){
+ releasePageNotNull(pCur->pPage);
+ while( --pCur->iPage ){
+ releasePageNotNull(pCur->apPage[pCur->iPage]);
+ }
+ pCur->pPage = pCur->apPage[0];
+ goto skip_init;
}
}else if( pCur->pgnoRoot==0 ){
pCur->eState = CURSOR_INVALID;
- return SQLITE_OK;
+ return SQLITE_EMPTY;
}else{
assert( pCur->iPage==(-1) );
- rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->apPage[0],
+ if( pCur->eState>=CURSOR_REQUIRESEEK ){
+ if( pCur->eState==CURSOR_FAULT ){
+ assert( pCur->skipNext!=SQLITE_OK );
+ return pCur->skipNext;
+ }
+ sqlite3BtreeClearCursor(pCur);
+ }
+ rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->pPage,
0, pCur->curPagerFlags);
if( rc!=SQLITE_OK ){
pCur->eState = CURSOR_INVALID;
return rc;
}
pCur->iPage = 0;
- pCur->curIntKey = pCur->apPage[0]->intKey;
+ pCur->curIntKey = pCur->pPage->intKey;
}
- pRoot = pCur->apPage[0];
+ pRoot = pCur->pPage;
assert( pRoot->pgno==pCur->pgnoRoot );
/* If pCur->pKeyInfo is not NULL, then the caller that opened this cursor
@@ -63133,13 +65464,15 @@ static int moveToRoot(BtCursor *pCur){
** (or the freelist). */
assert( pRoot->intKey==1 || pRoot->intKey==0 );
if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_CORRUPT_PAGE(pCur->pPage);
}
- pCur->aiIdx[0] = 0;
+skip_init:
+ pCur->ix = 0;
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl);
+ pRoot = pCur->pPage;
if( pRoot->nCell>0 ){
pCur->eState = CURSOR_VALID;
}else if( !pRoot->leaf ){
@@ -63150,6 +65483,7 @@ static int moveToRoot(BtCursor *pCur){
rc = moveToChild(pCur, subpage);
}else{
pCur->eState = CURSOR_INVALID;
+ rc = SQLITE_EMPTY;
}
return rc;
}
@@ -63168,9 +65502,9 @@ static int moveToLeftmost(BtCursor *pCur){
assert( cursorOwnsBtShared(pCur) );
assert( pCur->eState==CURSOR_VALID );
- while( rc==SQLITE_OK && !(pPage = pCur->apPage[pCur->iPage])->leaf ){
- assert( pCur->aiIdx[pCur->iPage]nCell );
- pgno = get4byte(findCell(pPage, pCur->aiIdx[pCur->iPage]));
+ while( rc==SQLITE_OK && !(pPage = pCur->pPage)->leaf ){
+ assert( pCur->ixnCell );
+ pgno = get4byte(findCell(pPage, pCur->ix));
rc = moveToChild(pCur, pgno);
}
return rc;
@@ -63193,13 +65527,13 @@ static int moveToRightmost(BtCursor *pCur){
assert( cursorOwnsBtShared(pCur) );
assert( pCur->eState==CURSOR_VALID );
- while( !(pPage = pCur->apPage[pCur->iPage])->leaf ){
+ while( !(pPage = pCur->pPage)->leaf ){
pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
- pCur->aiIdx[pCur->iPage] = pPage->nCell;
+ pCur->ix = pPage->nCell;
rc = moveToChild(pCur, pgno);
if( rc ) return rc;
}
- pCur->aiIdx[pCur->iPage] = pPage->nCell-1;
+ pCur->ix = pPage->nCell-1;
assert( pCur->info.nSize==0 );
assert( (pCur->curFlags & BTCF_ValidNKey)==0 );
return SQLITE_OK;
@@ -63216,14 +65550,13 @@ SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
rc = moveToRoot(pCur);
if( rc==SQLITE_OK ){
- if( pCur->eState==CURSOR_INVALID ){
- assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
- *pRes = 1;
- }else{
- assert( pCur->apPage[pCur->iPage]->nCell>0 );
- *pRes = 0;
- rc = moveToLeftmost(pCur);
- }
+ assert( pCur->pPage->nCell>0 );
+ *pRes = 0;
+ rc = moveToLeftmost(pCur);
+ }else if( rc==SQLITE_EMPTY ){
+ assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 );
+ *pRes = 1;
+ rc = SQLITE_OK;
}
return rc;
}
@@ -63247,28 +65580,26 @@ SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
for(ii=0; iiiPage; ii++){
assert( pCur->aiIdx[ii]==pCur->apPage[ii]->nCell );
}
- assert( pCur->aiIdx[pCur->iPage]==pCur->apPage[pCur->iPage]->nCell-1 );
- assert( pCur->apPage[pCur->iPage]->leaf );
+ assert( pCur->ix==pCur->pPage->nCell-1 );
+ assert( pCur->pPage->leaf );
#endif
return SQLITE_OK;
}
rc = moveToRoot(pCur);
if( rc==SQLITE_OK ){
- if( CURSOR_INVALID==pCur->eState ){
- assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
- *pRes = 1;
+ assert( pCur->eState==CURSOR_VALID );
+ *pRes = 0;
+ rc = moveToRightmost(pCur);
+ if( rc==SQLITE_OK ){
+ pCur->curFlags |= BTCF_AtLast;
}else{
- assert( pCur->eState==CURSOR_VALID );
- *pRes = 0;
- rc = moveToRightmost(pCur);
- if( rc==SQLITE_OK ){
- pCur->curFlags |= BTCF_AtLast;
- }else{
- pCur->curFlags &= ~BTCF_AtLast;
- }
-
+ pCur->curFlags &= ~BTCF_AtLast;
}
+ }else if( rc==SQLITE_EMPTY ){
+ assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 );
+ *pRes = 1;
+ rc = SQLITE_OK;
}
return rc;
}
@@ -63328,9 +65659,29 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
*pRes = 0;
return SQLITE_OK;
}
- if( (pCur->curFlags & BTCF_AtLast)!=0 && pCur->info.nKeyinfo.nKeycurFlags & BTCF_AtLast)!=0 ){
+ *pRes = -1;
+ return SQLITE_OK;
+ }
+ /* If the requested key is one more than the previous key, then
+ ** try to get there using sqlite3BtreeNext() rather than a full
+ ** binary search. This is an optimization only. The correct answer
+ ** is still obtained without this case, only a little more slowely */
+ if( pCur->info.nKey+1==intKey && !pCur->skipNext ){
+ *pRes = 0;
+ rc = sqlite3BtreeNext(pCur, 0);
+ if( rc==SQLITE_OK ){
+ getCellInfo(pCur);
+ if( pCur->info.nKey==intKey ){
+ return SQLITE_OK;
+ }
+ }else if( rc==SQLITE_DONE ){
+ rc = SQLITE_OK;
+ }else{
+ return rc;
+ }
+ }
}
}
@@ -63347,22 +65698,23 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
rc = moveToRoot(pCur);
if( rc ){
+ if( rc==SQLITE_EMPTY ){
+ assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 );
+ *pRes = -1;
+ return SQLITE_OK;
+ }
return rc;
}
- assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage] );
- assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->isInit );
- assert( pCur->eState==CURSOR_INVALID || pCur->apPage[pCur->iPage]->nCell>0 );
- if( pCur->eState==CURSOR_INVALID ){
- *pRes = -1;
- assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
- return SQLITE_OK;
- }
- assert( pCur->apPage[0]->intKey==pCur->curIntKey );
+ assert( pCur->pPage );
+ assert( pCur->pPage->isInit );
+ assert( pCur->eState==CURSOR_VALID );
+ assert( pCur->pPage->nCell > 0 );
+ assert( pCur->iPage==0 || pCur->apPage[0]->intKey==pCur->curIntKey );
assert( pCur->curIntKey || pIdxKey );
for(;;){
int lwr, upr, idx, c;
Pgno chldPg;
- MemPage *pPage = pCur->apPage[pCur->iPage];
+ MemPage *pPage = pCur->pPage;
u8 *pCell; /* Pointer to current cell in pPage */
/* pPage->nCell must be greater than zero. If this is the root-page
@@ -63377,14 +65729,16 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
upr = pPage->nCell-1;
assert( biasRight==0 || biasRight==1 );
idx = upr>>(1-biasRight); /* idx = biasRight ? upr : (lwr+upr)/2; */
- pCur->aiIdx[pCur->iPage] = (u16)idx;
+ pCur->ix = (u16)idx;
if( xRecordCompare==0 ){
for(;;){
i64 nCellKey;
pCell = findCellPastPtr(pPage, idx);
if( pPage->intKeyLeaf ){
while( 0x80 <= *(pCell++) ){
- if( pCell>=pPage->aDataEnd ) return SQLITE_CORRUPT_BKPT;
+ if( pCell>=pPage->aDataEnd ){
+ return SQLITE_CORRUPT_PAGE(pPage);
+ }
}
}
getVarint(pCell, (u64*)&nCellKey);
@@ -63396,16 +65750,16 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
if( lwr>upr ){ c = +1; break; }
}else{
assert( nCellKey==intKey );
- pCur->curFlags |= BTCF_ValidNKey;
- pCur->info.nKey = nCellKey;
- pCur->aiIdx[pCur->iPage] = (u16)idx;
+ pCur->ix = (u16)idx;
if( !pPage->leaf ){
lwr = idx;
goto moveto_next_layer;
}else{
+ pCur->curFlags |= BTCF_ValidNKey;
+ pCur->info.nKey = nCellKey;
+ pCur->info.nSize = 0;
*pRes = 0;
- rc = SQLITE_OK;
- goto moveto_finish;
+ return SQLITE_OK;
}
}
assert( lwr+upr>=0 );
@@ -63457,7 +65811,7 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
testcase( nCell==1 ); /* Invalid key size: 0x80 0x80 0x01 */
testcase( nCell==2 ); /* Minimum legal index key size */
if( nCell<2 ){
- rc = SQLITE_CORRUPT_BKPT;
+ rc = SQLITE_CORRUPT_PAGE(pPage);
goto moveto_finish;
}
pCellKey = sqlite3Malloc( nCell+18 );
@@ -63465,8 +65819,9 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
rc = SQLITE_NOMEM_BKPT;
goto moveto_finish;
}
- pCur->aiIdx[pCur->iPage] = (u16)idx;
- rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 2);
+ pCur->ix = (u16)idx;
+ rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0);
+ pCur->curFlags &= ~BTCF_ValidOvfl;
if( rc ){
sqlite3_free(pCellKey);
goto moveto_finish;
@@ -63486,8 +65841,8 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
assert( c==0 );
*pRes = 0;
rc = SQLITE_OK;
- pCur->aiIdx[pCur->iPage] = (u16)idx;
- if( pIdxKey->errCode ) rc = SQLITE_CORRUPT;
+ pCur->ix = (u16)idx;
+ if( pIdxKey->errCode ) rc = SQLITE_CORRUPT_BKPT;
goto moveto_finish;
}
if( lwr>upr ) break;
@@ -63498,8 +65853,8 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
assert( lwr==upr+1 || (pPage->intKey && !pPage->leaf) );
assert( pPage->isInit );
if( pPage->leaf ){
- assert( pCur->aiIdx[pCur->iPage]apPage[pCur->iPage]->nCell );
- pCur->aiIdx[pCur->iPage] = (u16)idx;
+ assert( pCur->ixpPage->nCell );
+ pCur->ix = (u16)idx;
*pRes = c;
rc = SQLITE_OK;
goto moveto_finish;
@@ -63510,13 +65865,13 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
}else{
chldPg = get4byte(findCell(pPage, lwr));
}
- pCur->aiIdx[pCur->iPage] = (u16)lwr;
+ pCur->ix = (u16)lwr;
rc = moveToChild(pCur, chldPg);
if( rc ) break;
}
moveto_finish:
pCur->info.nSize = 0;
- pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
+ assert( (pCur->curFlags & BTCF_ValidOvfl)==0 );
return rc;
}
@@ -63537,10 +65892,37 @@ SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor *pCur){
}
/*
-** Advance the cursor to the next entry in the database. If
-** 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.
+** Return an estimate for the number of rows in the table that pCur is
+** pointing to. Return a negative number if no estimate is currently
+** available.
+*/
+SQLITE_PRIVATE i64 sqlite3BtreeRowCountEst(BtCursor *pCur){
+ i64 n;
+ u8 i;
+
+ assert( cursorOwnsBtShared(pCur) );
+ assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
+
+ /* Currently this interface is only called by the OP_IfSmaller
+ ** opcode, and it that case the cursor will always be valid and
+ ** will always point to a leaf node. */
+ if( NEVER(pCur->eState!=CURSOR_VALID) ) return -1;
+ if( NEVER(pCur->pPage->leaf==0) ) return -1;
+
+ n = pCur->pPage->nCell;
+ for(i=0; iiPage; i++){
+ n *= pCur->apPage[i]->nCell;
+ }
+ return n;
+}
+
+/*
+** Advance the cursor to the next entry in the database.
+** Return value:
+**
+** SQLITE_OK success
+** SQLITE_DONE cursor is already pointing at the last element
+** otherwise some kind of error occurred
**
** The main entry point is sqlite3BtreeNext(). That routine is optimized
** for the common case of merely incrementing the cell counter BtCursor.aiIdx
@@ -63548,23 +65930,19 @@ SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor *pCur){
** routine is called when it is necessary to move to a different page or
** to restore the cursor.
**
-** The calling function will set *pRes to 0 or 1. The initial *pRes value
-** will be 1 if the cursor being stepped corresponds to an SQL index and
-** if this routine could have been skipped if that SQL index had been
-** a unique index. Otherwise the caller will have set *pRes to zero.
-** Zero is the common case. The btree implementation is free to use the
-** initial *pRes value as a hint to improve performance, but the current
-** SQLite btree implementation does not. (Note that the comdb2 btree
-** implementation does use this hint, however.)
+** If bit 0x01 of the F argument in sqlite3BtreeNext(C,F) is 1, then the
+** cursor corresponds to an SQL index and this routine could have been
+** skipped if the SQL index had been a unique index. The F argument
+** is a hint to the implement. SQLite btree implementation does not use
+** this hint, but COMDB2 does.
*/
-static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int *pRes){
+static SQLITE_NOINLINE int btreeNext(BtCursor *pCur){
int rc;
int idx;
MemPage *pPage;
assert( cursorOwnsBtShared(pCur) );
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
- assert( *pRes==0 );
if( pCur->eState!=CURSOR_VALID ){
assert( (pCur->curFlags & BTCF_ValidOvfl)==0 );
rc = restoreCursorPosition(pCur);
@@ -63572,8 +65950,7 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int *pRes){
return rc;
}
if( CURSOR_INVALID==pCur->eState ){
- *pRes = 1;
- return SQLITE_OK;
+ return SQLITE_DONE;
}
if( pCur->skipNext ){
assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_SKIPNEXT );
@@ -63586,8 +65963,8 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int *pRes){
}
}
- pPage = pCur->apPage[pCur->iPage];
- idx = ++pCur->aiIdx[pCur->iPage];
+ pPage = pCur->pPage;
+ idx = ++pCur->ix;
assert( pPage->isInit );
/* If the database file is corrupt, it is possible for the value of idx
@@ -63605,15 +65982,14 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int *pRes){
}
do{
if( pCur->iPage==0 ){
- *pRes = 1;
pCur->eState = CURSOR_INVALID;
- return SQLITE_OK;
+ return SQLITE_DONE;
}
moveToParent(pCur);
- pPage = pCur->apPage[pCur->iPage];
- }while( pCur->aiIdx[pCur->iPage]>=pPage->nCell );
+ pPage = pCur->pPage;
+ }while( pCur->ix>=pPage->nCell );
if( pPage->intKey ){
- return sqlite3BtreeNext(pCur, pRes);
+ return sqlite3BtreeNext(pCur, 0);
}else{
return SQLITE_OK;
}
@@ -63624,20 +66000,19 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int *pRes){
return moveToLeftmost(pCur);
}
}
-SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
+SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int flags){
MemPage *pPage;
+ UNUSED_PARAMETER( flags ); /* Used in COMDB2 but not native SQLite */
assert( cursorOwnsBtShared(pCur) );
- assert( pRes!=0 );
- assert( *pRes==0 || *pRes==1 );
+ assert( flags==0 || flags==1 );
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
- *pRes = 0;
- if( pCur->eState!=CURSOR_VALID ) return btreeNext(pCur, pRes);
- pPage = pCur->apPage[pCur->iPage];
- if( (++pCur->aiIdx[pCur->iPage])>=pPage->nCell ){
- pCur->aiIdx[pCur->iPage]--;
- return btreeNext(pCur, pRes);
+ if( pCur->eState!=CURSOR_VALID ) return btreeNext(pCur);
+ pPage = pCur->pPage;
+ if( (++pCur->ix)>=pPage->nCell ){
+ pCur->ix--;
+ return btreeNext(pCur);
}
if( pPage->leaf ){
return SQLITE_OK;
@@ -63647,10 +66022,12 @@ SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
}
/*
-** Step the cursor to the back to the previous entry in the database. If
-** 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.
+** Step the cursor to the back to the previous entry in the database.
+** Return values:
+**
+** SQLITE_OK success
+** SQLITE_DONE the cursor is already on the first element of the table
+** otherwise some kind of error occurred
**
** The main entry point is sqlite3BtreePrevious(). That routine is optimized
** for the common case of merely decrementing the cell counter BtCursor.aiIdx
@@ -63658,22 +66035,17 @@ SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
** helper routine is called when it is necessary to move to a different page
** or to restore the cursor.
**
-** The calling function will set *pRes to 0 or 1. The initial *pRes value
-** will be 1 if the cursor being stepped corresponds to an SQL index and
-** if this routine could have been skipped if that SQL index had been
-** a unique index. Otherwise the caller will have set *pRes to zero.
-** Zero is the common case. The btree implementation is free to use the
-** initial *pRes value as a hint to improve performance, but the current
-** SQLite btree implementation does not. (Note that the comdb2 btree
-** implementation does use this hint, however.)
+** If bit 0x01 of the F argument to sqlite3BtreePrevious(C,F) is 1, then
+** the cursor corresponds to an SQL index and this routine could have been
+** skipped if the SQL index had been a unique index. The F argument is a
+** hint to the implement. The native SQLite btree implementation does not
+** use this hint, but COMDB2 does.
*/
-static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){
+static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur){
int rc;
MemPage *pPage;
assert( cursorOwnsBtShared(pCur) );
- assert( pRes!=0 );
- assert( *pRes==0 );
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
assert( (pCur->curFlags & (BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey))==0 );
assert( pCur->info.nSize==0 );
@@ -63683,8 +66055,7 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){
return rc;
}
if( CURSOR_INVALID==pCur->eState ){
- *pRes = 1;
- return SQLITE_OK;
+ return SQLITE_DONE;
}
if( pCur->skipNext ){
assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_SKIPNEXT );
@@ -63697,50 +66068,48 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){
}
}
- pPage = pCur->apPage[pCur->iPage];
+ pPage = pCur->pPage;
assert( pPage->isInit );
if( !pPage->leaf ){
- int idx = pCur->aiIdx[pCur->iPage];
+ int idx = pCur->ix;
rc = moveToChild(pCur, get4byte(findCell(pPage, idx)));
if( rc ) return rc;
rc = moveToRightmost(pCur);
}else{
- while( pCur->aiIdx[pCur->iPage]==0 ){
+ while( pCur->ix==0 ){
if( pCur->iPage==0 ){
pCur->eState = CURSOR_INVALID;
- *pRes = 1;
- return SQLITE_OK;
+ return SQLITE_DONE;
}
moveToParent(pCur);
}
assert( pCur->info.nSize==0 );
- assert( (pCur->curFlags & (BTCF_ValidNKey|BTCF_ValidOvfl))==0 );
+ assert( (pCur->curFlags & (BTCF_ValidOvfl))==0 );
- pCur->aiIdx[pCur->iPage]--;
- pPage = pCur->apPage[pCur->iPage];
+ pCur->ix--;
+ pPage = pCur->pPage;
if( pPage->intKey && !pPage->leaf ){
- rc = sqlite3BtreePrevious(pCur, pRes);
+ rc = sqlite3BtreePrevious(pCur, 0);
}else{
rc = SQLITE_OK;
}
}
return rc;
}
-SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
+SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int flags){
assert( cursorOwnsBtShared(pCur) );
- assert( pRes!=0 );
- assert( *pRes==0 || *pRes==1 );
+ assert( flags==0 || flags==1 );
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
- *pRes = 0;
+ UNUSED_PARAMETER( flags ); /* Used in COMDB2 but not native SQLite */
pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey);
pCur->info.nSize = 0;
if( pCur->eState!=CURSOR_VALID
- || pCur->aiIdx[pCur->iPage]==0
- || pCur->apPage[pCur->iPage]->leaf==0
+ || pCur->ix==0
+ || pCur->pPage->leaf==0
){
- return btreePrevious(pCur, pRes);
+ return btreePrevious(pCur);
}
- pCur->aiIdx[pCur->iPage]--;
+ pCur->ix--;
return SQLITE_OK;
}
@@ -63846,7 +66215,7 @@ static int allocateBtreePage(
}
testcase( iTrunk==mxPage );
if( iTrunk>mxPage || nSearch++ > n ){
- rc = SQLITE_CORRUPT_BKPT;
+ rc = SQLITE_CORRUPT_PGNO(pPrevTrunk ? pPrevTrunk->pgno : 1);
}else{
rc = btreeGetUnusedPage(pBt, iTrunk, &pTrunk, 0);
}
@@ -63875,7 +66244,7 @@ static int allocateBtreePage(
TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1));
}else if( k>(u32)(pBt->usableSize/4 - 2) ){
/* Value of k is out of range. Database corruption */
- rc = SQLITE_CORRUPT_BKPT;
+ rc = SQLITE_CORRUPT_PGNO(iTrunk);
goto end_allocate_page;
#ifndef SQLITE_OMIT_AUTOVACUUM
}else if( searchList
@@ -63909,7 +66278,7 @@ static int allocateBtreePage(
MemPage *pNewTrunk;
Pgno iNewTrunk = get4byte(&pTrunk->aData[8]);
if( iNewTrunk>mxPage ){
- rc = SQLITE_CORRUPT_BKPT;
+ rc = SQLITE_CORRUPT_PGNO(iTrunk);
goto end_allocate_page;
}
testcase( iNewTrunk==mxPage );
@@ -63974,7 +66343,7 @@ static int allocateBtreePage(
iPage = get4byte(&aData[8+closest*4]);
testcase( iPage==mxPage );
if( iPage>mxPage ){
- rc = SQLITE_CORRUPT_BKPT;
+ rc = SQLITE_CORRUPT_PGNO(iTrunk);
goto end_allocate_page;
}
testcase( iPage==mxPage );
@@ -64230,30 +66599,30 @@ static void freePage(MemPage *pPage, int *pRC){
static int clearCell(
MemPage *pPage, /* The page that contains the Cell */
unsigned char *pCell, /* First byte of the Cell */
- u16 *pnSize /* Write the size of the Cell here */
+ CellInfo *pInfo /* Size information about the cell */
){
- BtShared *pBt = pPage->pBt;
- CellInfo info;
+ BtShared *pBt;
Pgno ovflPgno;
int rc;
int nOvfl;
u32 ovflPageSize;
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- pPage->xParseCell(pPage, pCell, &info);
- *pnSize = info.nSize;
- if( info.nLocal==info.nPayload ){
+ pPage->xParseCell(pPage, pCell, pInfo);
+ if( pInfo->nLocal==pInfo->nPayload ){
return SQLITE_OK; /* No overflow pages. Return without doing anything */
}
- if( pCell+info.nSize-1 > pPage->aData+pPage->maskPage ){
- return SQLITE_CORRUPT_BKPT; /* Cell extends past end of page */
+ if( pCell+pInfo->nSize-1 > pPage->aData+pPage->maskPage ){
+ /* Cell extends past end of page */
+ return SQLITE_CORRUPT_PAGE(pPage);
}
- ovflPgno = get4byte(pCell + info.nSize - 4);
+ ovflPgno = get4byte(pCell + pInfo->nSize - 4);
+ pBt = pPage->pBt;
assert( pBt->usableSize > 4 );
ovflPageSize = pBt->usableSize - 4;
- nOvfl = (info.nPayload - info.nLocal + ovflPageSize - 1)/ovflPageSize;
+ nOvfl = (pInfo->nPayload - pInfo->nLocal + ovflPageSize - 1)/ovflPageSize;
assert( nOvfl>0 ||
- (CORRUPT_DB && (info.nPayload + ovflPageSize)nPayload + ovflPageSize)pBt;
- Pgno pgnoOvfl = 0;
+ BtShared *pBt;
+ Pgno pgnoOvfl;
int nHeader;
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
/* pPage is not necessarily writeable since pCell might be auxiliary
** buffer space that is separate from the pPage buffer area */
- assert( pCellaData || pCell>=&pPage->aData[pBt->pageSize]
+ assert( pCellaData || pCell>=&pPage->aData[pPage->pBt->pageSize]
|| sqlite3PagerIswriteable(pPage->pDbPage) );
/* Fill in the header. */
@@ -64350,25 +66718,36 @@ static int fillInCell(
}
/* Fill in the payload */
+ pPayload = &pCell[nHeader];
if( nPayload<=pPage->maxLocal ){
+ /* This is the common case where everything fits on the btree page
+ ** and no overflow pages are required. */
n = nHeader + nPayload;
testcase( n==3 );
testcase( n==4 );
if( n<4 ) n = 4;
*pnSize = n;
- spaceLeft = nPayload;
- pPrior = pCell;
- }else{
- int mn = pPage->minLocal;
- n = mn + (nPayload - mn) % (pPage->pBt->usableSize - 4);
- testcase( n==pPage->maxLocal );
- testcase( n==pPage->maxLocal+1 );
- if( n > pPage->maxLocal ) n = mn;
- spaceLeft = n;
- *pnSize = n + nHeader + 4;
- pPrior = &pCell[nHeader+n];
+ assert( nSrc<=nPayload );
+ testcase( nSrcminLocal;
+ n = mn + (nPayload - mn) % (pPage->pBt->usableSize - 4);
+ testcase( n==pPage->maxLocal );
+ testcase( n==pPage->maxLocal+1 );
+ if( n > pPage->maxLocal ) n = mn;
+ spaceLeft = n;
+ *pnSize = n + nHeader + 4;
+ pPrior = &pCell[nHeader+n];
+ pToRelease = 0;
+ pgnoOvfl = 0;
+ pBt = pPage->pBt;
/* At this point variables should be set as follows:
**
@@ -64382,7 +66761,7 @@ static int fillInCell(
** Use a call to btreeParseCellPtr() to verify that the values above
** were computed correctly.
*/
-#if SQLITE_DEBUG
+#ifdef SQLITE_DEBUG
{
CellInfo info;
pPage->xParseCell(pPage, pCell, &info);
@@ -64394,8 +66773,35 @@ static int fillInCell(
#endif
/* Write the payload into the local Cell and any extra into overflow pages */
- while( nPayload>0 ){
+ while( 1 ){
+ n = nPayload;
+ if( n>spaceLeft ) n = spaceLeft;
+
+ /* If pToRelease is not zero than pPayload points into the data area
+ ** of pToRelease. Make sure pToRelease is still writeable. */
+ assert( pToRelease==0 || sqlite3PagerIswriteable(pToRelease->pDbPage) );
+
+ /* If pPayload is part of the data area of pPage, then make sure pPage
+ ** is still writeable */
+ assert( pPayloadaData || pPayload>=&pPage->aData[pBt->pageSize]
+ || sqlite3PagerIswriteable(pPage->pDbPage) );
+
+ if( nSrc>=n ){
+ memcpy(pPayload, pSrc, n);
+ }else if( nSrc>0 ){
+ n = nSrc;
+ memcpy(pPayload, pSrc, n);
+ }else{
+ memset(pPayload, 0, n);
+ }
+ nPayload -= n;
+ if( nPayload<=0 ) break;
+ pPayload += n;
+ pSrc += n;
+ nSrc -= n;
+ spaceLeft -= n;
if( spaceLeft==0 ){
+ MemPage *pOvfl = 0;
#ifndef SQLITE_OMIT_AUTOVACUUM
Pgno pgnoPtrmap = pgnoOvfl; /* Overflow page pointer-map entry page */
if( pBt->autoVacuum ){
@@ -64448,30 +66854,6 @@ static int fillInCell(
pPayload = &pOvfl->aData[4];
spaceLeft = pBt->usableSize - 4;
}
- n = nPayload;
- if( n>spaceLeft ) n = spaceLeft;
-
- /* If pToRelease is not zero than pPayload points into the data area
- ** of pToRelease. Make sure pToRelease is still writeable. */
- assert( pToRelease==0 || sqlite3PagerIswriteable(pToRelease->pDbPage) );
-
- /* If pPayload is part of the data area of pPage, then make sure pPage
- ** is still writeable */
- assert( pPayloadaData || pPayload>=&pPage->aData[pBt->pageSize]
- || sqlite3PagerIswriteable(pPage->pDbPage) );
-
- if( nSrc>0 ){
- if( n>nSrc ) n = nSrc;
- assert( pSrc );
- memcpy(pPayload, pSrc, n);
- }else{
- memset(pPayload, 0, n);
- }
- nPayload -= n;
- pPayload += n;
- pSrc += n;
- nSrc -= n;
- spaceLeft -= n;
}
releasePage(pToRelease);
return SQLITE_OK;
@@ -64493,7 +66875,6 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){
int hdr; /* Beginning of the header. 0 most pages. 100 page 1 */
if( *pRC ) return;
-
assert( idx>=0 && idxnCell );
assert( CORRUPT_DB || sz==cellSize(pPage, idx) );
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
@@ -64504,7 +66885,7 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){
hdr = pPage->hdrOffset;
testcase( pc==get2byte(&data[hdr+5]) );
testcase( pc+sz==pPage->pBt->usableSize );
- if( pc < (u32)get2byte(&data[hdr+5]) || pc+sz > pPage->pBt->usableSize ){
+ if( pc+sz > pPage->pBt->usableSize ){
*pRC = SQLITE_CORRUPT_BKPT;
return;
}
@@ -64577,7 +66958,10 @@ static void insertCell(
put4byte(pCell, iChild);
}
j = pPage->nOverflow++;
- assert( j<(int)(sizeof(pPage->apOvfl)/sizeof(pPage->apOvfl[0])) );
+ /* Comparison against ArraySize-1 since we hold back one extra slot
+ ** as a contingency. In other words, never need more than 3 overflow
+ ** slots but 4 are allocated, just to be safe. */
+ assert( j < ArraySize(pPage->apOvfl)-1 );
pPage->apOvfl[j] = pCell;
pPage->aiOvfl[j] = (u16)i;
@@ -65317,7 +67701,7 @@ static int balance_nonroot(
nMaxCells += 1+apOld[i]->nCell+apOld[i]->nOverflow;
if( (i--)==0 ) break;
- if( i+nxDiv==pParent->aiOvfl[0] && pParent->nOverflow ){
+ if( pParent->nOverflow && i+nxDiv==pParent->aiOvfl[0] ){
apDiv[i] = pParent->apOvfl[0];
pgno = get4byte(apDiv[i]);
szNew[i] = pParent->xCellSize(pParent, apDiv[i]);
@@ -65339,7 +67723,7 @@ static int balance_nonroot(
** In this case, temporarily copy the cell into the aOvflSpace[]
** buffer. It will be copied out again as soon as the aSpace[] buffer
** is allocated. */
- if( pBt->btsFlags & BTS_SECURE_DELETE ){
+ if( pBt->btsFlags & BTS_FAST_SECURE ){
int iOff;
iOff = SQLITE_PTR_TO_INT(apDiv[i]) - SQLITE_PTR_TO_INT(pParent->aData);
@@ -65368,10 +67752,8 @@ static int balance_nonroot(
+ nMaxCells*sizeof(u16) /* b.szCell */
+ pBt->pageSize; /* aSpace1 */
- /* EVIDENCE-OF: R-28375-38319 SQLite will never request a scratch buffer
- ** that is more than 6 times the database page size. */
assert( szScratch<=6*(int)pBt->pageSize );
- b.apCell = sqlite3ScratchMalloc( szScratch );
+ b.apCell = sqlite3StackAllocRaw(0, szScratch );
if( b.apCell==0 ){
rc = SQLITE_NOMEM_BKPT;
goto balance_cleanup;
@@ -65509,7 +67891,6 @@ static int balance_nonroot(
for(i=0; inFree;
- if( szNew[i]<0 ){ rc = SQLITE_CORRUPT_BKPT; goto balance_cleanup; }
for(j=0; jnOverflow; j++){
szNew[i] += 2 + p->xCellSize(p, p->apOvfl[j]);
}
@@ -65907,7 +68288,7 @@ static int balance_nonroot(
** free space needs to be up front.
*/
assert( nNew==1 || CORRUPT_DB );
- rc = defragmentPage(apNew[0]);
+ rc = defragmentPage(apNew[0], -1);
testcase( rc!=SQLITE_OK );
assert( apNew[0]->nFree ==
(get2byte(&apNew[0]->aData[5])-apNew[0]->cellOffset-apNew[0]->nCell*2)
@@ -65950,7 +68331,7 @@ static int balance_nonroot(
** Cleanup before returning.
*/
balance_cleanup:
- sqlite3ScratchFree(b.apCell);
+ sqlite3StackFree(0, b.apCell);
for(i=0; iiPage;
- MemPage *pPage = pCur->apPage[iPage];
+ MemPage *pPage = pCur->pPage;
if( iPage==0 ){
if( pPage->nOverflow ){
@@ -66063,9 +68444,11 @@ static int balance(BtCursor *pCur){
rc = balance_deeper(pPage, &pCur->apPage[1]);
if( rc==SQLITE_OK ){
pCur->iPage = 1;
+ pCur->ix = 0;
pCur->aiIdx[0] = 0;
- pCur->aiIdx[1] = 0;
- assert( pCur->apPage[1]->nOverflow );
+ pCur->apPage[0] = pPage;
+ pCur->pPage = pCur->apPage[1];
+ assert( pCur->pPage->nOverflow );
}
}else{
break;
@@ -66145,6 +68528,7 @@ static int balance(BtCursor *pCur){
releasePage(pPage);
pCur->iPage--;
assert( pCur->iPage>=0 );
+ pCur->pPage = pCur->apPage[pCur->iPage];
}
}while( rc==SQLITE_OK );
@@ -66171,22 +68555,24 @@ static int balance(BtCursor *pCur){
** pX.pData,nData,nZero fields must be zero.
**
** If the seekResult parameter is non-zero, then a successful call to
-** MovetoUnpacked() to seek cursor pCur to (pKey, nKey) has already
-** been performed. seekResult is the search result returned (a negative
-** number if pCur points at an entry that is smaller than (pKey, nKey), or
-** a positive value if pCur points at an entry that is larger than
-** (pKey, nKey)).
-**
-** If the seekResult parameter is non-zero, then the caller guarantees that
-** cursor pCur is pointing at the existing copy of a row that is to be
-** overwritten. If the seekResult parameter is 0, then cursor pCur may
-** point to any entry or to no entry at all and so this function has to seek
-** the cursor before the new key can be inserted.
+** MovetoUnpacked() to seek cursor pCur to (pKey,nKey) has already
+** been performed. In other words, if seekResult!=0 then the cursor
+** is currently pointing to a cell that will be adjacent to the cell
+** to be inserted. If seekResult<0 then pCur points to a cell that is
+** smaller then (pKey,nKey). If seekResult>0 then pCur points to a cell
+** that is larger than (pKey,nKey).
+**
+** If seekResult==0, that means pCur is pointing at some unknown location.
+** In that case, this routine must seek the cursor to the correct insertion
+** point for (pKey,nKey) before doing the insertion. For index btrees,
+** if pX->nMem is non-zero, then pX->aMem contains pointers to the unpacked
+** key values and pX->aMem can be used instead of pX->pKey to avoid having
+** to decode the key.
*/
SQLITE_PRIVATE int sqlite3BtreeInsert(
BtCursor *pCur, /* Insert data into the table of this cursor */
const BtreePayload *pX, /* Content of the row to be inserted */
- int appendBias, /* True if this is likely an append */
+ int flags, /* True if this is likely an append */
int seekResult /* Result of prior MovetoUnpacked() call */
){
int rc;
@@ -66199,6 +68585,8 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
unsigned char *oldCell;
unsigned char *newCell = 0;
+ assert( (flags & (BTREE_SAVEPOSITION|BTREE_APPEND))==flags );
+
if( pCur->eState==CURSOR_FAULT ){
assert( pCur->skipNext!=SQLITE_OK );
return pCur->skipNext;
@@ -66237,25 +68625,42 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
assert( pX->pKey==0 );
/* If this is an insert into a table b-tree, invalidate any incrblob
** cursors open on the row being replaced */
- invalidateIncrblobCursors(p, pX->nKey, 0);
+ invalidateIncrblobCursors(p, pCur->pgnoRoot, pX->nKey, 0);
+
+ /* If BTREE_SAVEPOSITION is set, the cursor must already be pointing
+ ** to a row with the same key as the new entry being inserted. */
+ assert( (flags & BTREE_SAVEPOSITION)==0 ||
+ ((pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey==pCur->info.nKey) );
/* If the cursor is currently on the last row and we are appending a
** new row onto the end, set the "loc" to avoid an unnecessary
** btreeMoveto() call */
- if( (pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey>0
- && pCur->info.nKey==pX->nKey-1 ){
- loc = -1;
+ if( (pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey==pCur->info.nKey ){
+ loc = 0;
}else if( loc==0 ){
- rc = sqlite3BtreeMovetoUnpacked(pCur, 0, pX->nKey, appendBias, &loc);
+ rc = sqlite3BtreeMovetoUnpacked(pCur, 0, pX->nKey, flags!=0, &loc);
if( rc ) return rc;
}
- }else if( loc==0 ){
- rc = btreeMoveto(pCur, pX->pKey, pX->nKey, appendBias, &loc);
+ }else if( loc==0 && (flags & BTREE_SAVEPOSITION)==0 ){
+ if( pX->nMem ){
+ UnpackedRecord r;
+ r.pKeyInfo = pCur->pKeyInfo;
+ r.aMem = pX->aMem;
+ r.nField = pX->nMem;
+ r.default_rc = 0;
+ r.errCode = 0;
+ r.r1 = 0;
+ r.r2 = 0;
+ r.eqSeen = 0;
+ rc = sqlite3BtreeMovetoUnpacked(pCur, &r, 0, flags!=0, &loc);
+ }else{
+ rc = btreeMoveto(pCur, pX->pKey, pX->nKey, flags!=0, &loc);
+ }
if( rc ) return rc;
}
assert( pCur->eState==CURSOR_VALID || (pCur->eState==CURSOR_INVALID && loc) );
- pPage = pCur->apPage[pCur->iPage];
+ pPage = pCur->pPage;
assert( pPage->intKey || pX->nKey>=0 );
assert( pPage->leaf || !pPage->intKey );
@@ -66269,9 +68674,9 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
if( rc ) goto end_insert;
assert( szNew==pPage->xCellSize(pPage, newCell) );
assert( szNew <= MX_CELL_SIZE(pBt) );
- idx = pCur->aiIdx[pCur->iPage];
+ idx = pCur->ix;
if( loc==0 ){
- u16 szOld;
+ CellInfo info;
assert( idxnCell );
rc = sqlite3PagerWrite(pPage->pDbPage);
if( rc ){
@@ -66281,12 +68686,30 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
if( !pPage->leaf ){
memcpy(newCell, oldCell, 4);
}
- rc = clearCell(pPage, oldCell, &szOld);
- dropCell(pPage, idx, szOld, &rc);
+ rc = clearCell(pPage, oldCell, &info);
+ if( info.nSize==szNew && info.nLocal==info.nPayload
+ && (!ISAUTOVACUUM || szNewminLocal)
+ ){
+ /* Overwrite the old cell with the new if they are the same size.
+ ** We could also try to do this if the old cell is smaller, then add
+ ** the leftover space to the free list. But experiments show that
+ ** doing that is no faster then skipping this optimization and just
+ ** calling dropCell() and insertCell().
+ **
+ ** This optimization cannot be used on an autovacuum database if the
+ ** new entry uses overflow pages, as the insertCell() call below is
+ ** necessary to add the PTRMAP_OVERFLOW1 pointer-map entry. */
+ assert( rc==SQLITE_OK ); /* clearCell never fails when nLocal==nPayload */
+ if( oldCell+szNew > pPage->aDataEnd ) return SQLITE_CORRUPT_BKPT;
+ memcpy(oldCell, newCell, szNew);
+ return SQLITE_OK;
+ }
+ dropCell(pPage, idx, info.nSize, &rc);
if( rc ) goto end_insert;
}else if( loc<0 && pPage->nCell>0 ){
assert( pPage->leaf );
- idx = ++pCur->aiIdx[pCur->iPage];
+ idx = ++pCur->ix;
+ pCur->curFlags &= ~BTCF_ValidNKey;
}else{
assert( pPage->leaf );
}
@@ -66324,10 +68747,24 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
** fails. Internal data structure corruption will result otherwise.
** Also, set the cursor state to invalid. This stops saveCursorPosition()
** from trying to save the current position of the cursor. */
- pCur->apPage[pCur->iPage]->nOverflow = 0;
+ pCur->pPage->nOverflow = 0;
pCur->eState = CURSOR_INVALID;
+ if( (flags & BTREE_SAVEPOSITION) && rc==SQLITE_OK ){
+ btreeReleaseAllCursorPages(pCur);
+ if( pCur->pKeyInfo ){
+ assert( pCur->pKey==0 );
+ pCur->pKey = sqlite3Malloc( pX->nKey );
+ if( pCur->pKey==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ memcpy(pCur->pKey, pX->pKey, pX->nKey);
+ }
+ }
+ pCur->eState = CURSOR_REQUIRESEEK;
+ pCur->nKey = pX->nKey;
+ }
}
- assert( pCur->apPage[pCur->iPage]->nOverflow==0 );
+ assert( pCur->iPage<0 || pCur->pPage->nOverflow==0 );
end_insert:
return rc;
@@ -66358,7 +68795,7 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
unsigned char *pCell; /* Pointer to cell to delete */
int iCellIdx; /* Index of cell to delete */
int iCellDepth; /* Depth of node containing pCell */
- u16 szCell; /* Size of the cell being deleted */
+ CellInfo info; /* Size of the cell being deleted */
int bSkipnext = 0; /* Leaf cursor in SKIPNEXT state */
u8 bPreserve = flags & BTREE_SAVEPOSITION; /* Keep cursor valid */
@@ -66368,13 +68805,13 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
assert( pCur->curFlags & BTCF_WriteFlag );
assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
assert( !hasReadConflicts(p, pCur->pgnoRoot) );
- assert( pCur->aiIdx[pCur->iPage]apPage[pCur->iPage]->nCell );
+ assert( pCur->ixpPage->nCell );
assert( pCur->eState==CURSOR_VALID );
assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_AUXDELETE))==0 );
iCellDepth = pCur->iPage;
- iCellIdx = pCur->aiIdx[iCellDepth];
- pPage = pCur->apPage[iCellDepth];
+ iCellIdx = pCur->ix;
+ pPage = pCur->pPage;
pCell = findCell(pPage, iCellIdx);
/* If the bPreserve flag is set to true, then the cursor position must
@@ -66407,8 +68844,8 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
** sub-tree headed by the child page of the cell being deleted. This makes
** balancing the tree following the delete operation easier. */
if( !pPage->leaf ){
- int notUsed = 0;
- rc = sqlite3BtreePrevious(pCur, ¬Used);
+ rc = sqlite3BtreePrevious(pCur, 0);
+ assert( rc!=SQLITE_DONE );
if( rc ) return rc;
}
@@ -66422,7 +68859,7 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
/* If this is a delete operation to remove a row from a table b-tree,
** invalidate any incrblob cursors open on the row being deleted. */
if( pCur->pKeyInfo==0 ){
- invalidateIncrblobCursors(p, pCur->info.nKey, 0);
+ invalidateIncrblobCursors(p, pCur->pgnoRoot, pCur->info.nKey, 0);
}
/* Make the page containing the entry to be deleted writable. Then free any
@@ -66430,8 +68867,8 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
** itself from within the page. */
rc = sqlite3PagerWrite(pPage->pDbPage);
if( rc ) return rc;
- rc = clearCell(pPage, pCell, &szCell);
- dropCell(pPage, iCellIdx, szCell, &rc);
+ rc = clearCell(pPage, pCell, &info);
+ dropCell(pPage, iCellIdx, info.nSize, &rc);
if( rc ) return rc;
/* If the cell deleted was not located on a leaf page, then the cursor
@@ -66440,11 +68877,16 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
** node. The cell from the leaf node needs to be moved to the internal
** node to replace the deleted cell. */
if( !pPage->leaf ){
- MemPage *pLeaf = pCur->apPage[pCur->iPage];
+ MemPage *pLeaf = pCur->pPage;
int nCell;
- Pgno n = pCur->apPage[iCellDepth+1]->pgno;
+ Pgno n;
unsigned char *pTmp;
+ if( iCellDepthiPage-1 ){
+ n = pCur->apPage[iCellDepth+1]->pgno;
+ }else{
+ n = pCur->pPage->pgno;
+ }
pCell = findCell(pLeaf, pLeaf->nCell-1);
if( pCell<&pLeaf->aData[4] ) return SQLITE_CORRUPT_BKPT;
nCell = pLeaf->xCellSize(pLeaf, pCell);
@@ -66476,29 +68918,34 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
** well. */
rc = balance(pCur);
if( rc==SQLITE_OK && pCur->iPage>iCellDepth ){
+ releasePageNotNull(pCur->pPage);
+ pCur->iPage--;
while( pCur->iPage>iCellDepth ){
releasePage(pCur->apPage[pCur->iPage--]);
}
+ pCur->pPage = pCur->apPage[pCur->iPage];
rc = balance(pCur);
}
if( rc==SQLITE_OK ){
if( bSkipnext ){
assert( bPreserve && (pCur->iPage==iCellDepth || CORRUPT_DB) );
- assert( pPage==pCur->apPage[pCur->iPage] || CORRUPT_DB );
+ assert( pPage==pCur->pPage || CORRUPT_DB );
assert( (pPage->nCell>0 || CORRUPT_DB) && iCellIdx<=pPage->nCell );
pCur->eState = CURSOR_SKIPNEXT;
if( iCellIdx>=pPage->nCell ){
pCur->skipNext = -1;
- pCur->aiIdx[iCellDepth] = pPage->nCell-1;
+ pCur->ix = pPage->nCell-1;
}else{
pCur->skipNext = 1;
}
}else{
rc = moveToRoot(pCur);
if( bPreserve ){
+ btreeReleaseAllCursorPages(pCur);
pCur->eState = CURSOR_REQUIRESEEK;
}
+ if( rc==SQLITE_EMPTY ) rc = SQLITE_OK;
}
}
return rc;
@@ -66681,7 +69128,7 @@ static int clearDatabasePage(
unsigned char *pCell;
int i;
int hdr;
- u16 szCell;
+ CellInfo info;
assert( sqlite3_mutex_held(pBt->mutex) );
if( pgno>btreePagecount(pBt) ){
@@ -66701,7 +69148,7 @@ static int clearDatabasePage(
rc = clearDatabasePage(pBt, get4byte(pCell), 1, pnChange);
if( rc ) goto cleardatabasepage_out;
}
- rc = clearCell(pPage, pCell, &szCell);
+ rc = clearCell(pPage, pCell, &info);
if( rc ) goto cleardatabasepage_out;
}
if( !pPage->leaf ){
@@ -66749,7 +69196,7 @@ SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree *p, int iTable, int *pnChange){
/* Invalidate all incrblob cursors open on table iTable (assuming iTable
** is the root of a table b-tree - if it is not, the following call is
** a no-op). */
- invalidateIncrblobCursors(p, 0, 1);
+ invalidateIncrblobCursors(p, (Pgno)iTable, 0, 1);
rc = clearDatabasePage(pBt, (Pgno)iTable, 0, pnChange);
}
sqlite3BtreeLeave(p);
@@ -66792,27 +69239,7 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
assert( sqlite3BtreeHoldsMutex(p) );
assert( p->inTrans==TRANS_WRITE );
-
- /* It is illegal to drop a table if any cursors are open on the
- ** database. This is because in auto-vacuum mode the backend may
- ** need to move another root-page to fill a gap left by the deleted
- ** root page. If an open cursor was using this page a problem would
- ** occur.
- **
- ** This error is caught long before control reaches this point.
- */
- if( NEVER(pBt->pCursor) ){
- sqlite3ConnectionBlocked(p->db, pBt->pCursor->pBtree->db);
- return SQLITE_LOCKED_SHAREDCACHE;
- }
-
- /*
- ** It is illegal to drop the sqlite_master table on page 1. But again,
- ** this error is caught long before reaching this point.
- */
- if( NEVER(iTable<2) ){
- return SQLITE_CORRUPT_BKPT;
- }
+ assert( iTable>=2 );
rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0);
if( rc ) return rc;
@@ -66983,11 +69410,11 @@ SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
i64 nEntry = 0; /* Value to return in *pnEntry */
int rc; /* Return code */
- if( pCur->pgnoRoot==0 ){
+ rc = moveToRoot(pCur);
+ if( rc==SQLITE_EMPTY ){
*pnEntry = 0;
return SQLITE_OK;
}
- rc = moveToRoot(pCur);
/* Unless an error occurs, the following loop runs one iteration for each
** page in the B-Tree structure (not including overflow pages).
@@ -67000,7 +69427,7 @@ SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
** this page contains countable entries. Increment the entry counter
** accordingly.
*/
- pPage = pCur->apPage[pCur->iPage];
+ pPage = pCur->pPage;
if( pPage->leaf || !pPage->intKey ){
nEntry += pPage->nCell;
}
@@ -67023,16 +69450,16 @@ SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
return moveToRoot(pCur);
}
moveToParent(pCur);
- }while ( pCur->aiIdx[pCur->iPage]>=pCur->apPage[pCur->iPage]->nCell );
+ }while ( pCur->ix>=pCur->pPage->nCell );
- pCur->aiIdx[pCur->iPage]++;
- pPage = pCur->apPage[pCur->iPage];
+ pCur->ix++;
+ pPage = pCur->pPage;
}
/* Descend to the child node of the cell that the cursor currently
** points at. This is the right-child if (iIdx==pPage->nCell).
*/
- iIdx = pCur->aiIdx[pCur->iPage];
+ iIdx = pCur->ix;
if( iIdx==pPage->nCell ){
rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8]));
}else{
@@ -67417,6 +69844,7 @@ static int checkTreePage(
checkAppendMsg(pCheck, "Rowid %lld out of order", info.nKey);
}
maxKey = info.nKey;
+ keyCanBeEqual = 0; /* Only the first key on the page may ==maxKey */
}
/* Check the content overflow list */
@@ -67720,7 +70148,7 @@ SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree *p, int eMode, int *pnLog, int *
if( pBt->inTransaction!=TRANS_NONE ){
rc = SQLITE_LOCKED;
}else{
- rc = sqlite3PagerCheckpoint(pBt->pPager, eMode, pnLog, pnCkpt);
+ rc = sqlite3PagerCheckpoint(pBt->pPager, p->db, eMode, pnLog, pnCkpt);
}
sqlite3BtreeLeave(p);
}
@@ -67866,7 +70294,7 @@ SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void
&& pCsr->pBt->inTransaction==TRANS_WRITE );
assert( hasSharedCacheTableLock(pCsr->pBtree, pCsr->pgnoRoot, 0, 2) );
assert( !hasReadConflicts(pCsr->pBtree, pCsr->pgnoRoot) );
- assert( pCsr->apPage[pCsr->iPage]->intKey );
+ assert( pCsr->pPage->intKey );
return accessPayload(pCsr, offset, amt, (unsigned char *)z, 1);
}
@@ -68789,7 +71217,7 @@ SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){
*/
SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem *p){
/* If MEM_Dyn is set then Mem.xDel!=0.
- ** Mem.xDel is might not be initialized if MEM_Dyn is clear.
+ ** Mem.xDel might not be initialized if MEM_Dyn is clear.
*/
assert( (p->flags & MEM_Dyn)==0 || p->xDel!=0 );
@@ -68802,6 +71230,35 @@ SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem *p){
/* Cannot be both MEM_Int and MEM_Real at the same time */
assert( (p->flags & (MEM_Int|MEM_Real))!=(MEM_Int|MEM_Real) );
+ if( p->flags & MEM_Null ){
+ /* Cannot be both MEM_Null and some other type */
+ assert( (p->flags & (MEM_Int|MEM_Real|MEM_Str|MEM_Blob
+ |MEM_RowSet|MEM_Frame|MEM_Agg))==0 );
+
+ /* If MEM_Null is set, then either the value is a pure NULL (the usual
+ ** case) or it is a pointer set using sqlite3_bind_pointer() or
+ ** sqlite3_result_pointer(). If a pointer, then MEM_Term must also be
+ ** set.
+ */
+ if( (p->flags & (MEM_Term|MEM_Subtype))==(MEM_Term|MEM_Subtype) ){
+ /* This is a pointer type. There may be a flag to indicate what to
+ ** do with the pointer. */
+ assert( ((p->flags&MEM_Dyn)!=0 ? 1 : 0) +
+ ((p->flags&MEM_Ephem)!=0 ? 1 : 0) +
+ ((p->flags&MEM_Static)!=0 ? 1 : 0) <= 1 );
+
+ /* No other bits set */
+ assert( (p->flags & ~(MEM_Null|MEM_Term|MEM_Subtype
+ |MEM_Dyn|MEM_Ephem|MEM_Static))==0 );
+ }else{
+ /* A pure NULL might have other flags, such as MEM_Static, MEM_Dyn,
+ ** MEM_Ephem, MEM_Cleared, or MEM_Subtype */
+ }
+ }else{
+ /* The MEM_Cleared bit is only allowed on NULLs */
+ assert( (p->flags & MEM_Cleared)==0 );
+ }
+
/* The szMalloc field holds the correct memory allocation size */
assert( p->szMalloc==0
|| p->szMalloc==sqlite3DbMallocSize(p->db,p->zMalloc) );
@@ -68887,26 +71344,25 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPre
assert( pMem->szMalloc==0
|| pMem->szMalloc==sqlite3DbMallocSize(pMem->db, pMem->zMalloc) );
- if( pMem->szMallocszMalloc>0 && pMem->z==pMem->zMalloc ){
- pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
- bPreserve = 0;
- }else{
- if( pMem->szMalloc>0 ) sqlite3DbFree(pMem->db, pMem->zMalloc);
- pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n);
- }
- if( pMem->zMalloc==0 ){
- sqlite3VdbeMemSetNull(pMem);
- pMem->z = 0;
- pMem->szMalloc = 0;
- return SQLITE_NOMEM_BKPT;
- }else{
- pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc);
- }
+ if( n<32 ) n = 32;
+ if( pMem->szMalloc>0 && bPreserve && pMem->z==pMem->zMalloc ){
+ pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
+ bPreserve = 0;
+ }else{
+ if( pMem->szMalloc>0 ) sqlite3DbFreeNN(pMem->db, pMem->zMalloc);
+ pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n);
+ }
+ if( pMem->zMalloc==0 ){
+ sqlite3VdbeMemSetNull(pMem);
+ pMem->z = 0;
+ pMem->szMalloc = 0;
+ return SQLITE_NOMEM_BKPT;
+ }else{
+ pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc);
}
- if( bPreserve && pMem->z && pMem->z!=pMem->zMalloc ){
+ if( bPreserve && pMem->z ){
+ assert( pMem->z!=pMem->zMalloc );
memcpy(pMem->zMalloc, pMem->z, pMem->n);
}
if( (pMem->flags&MEM_Dyn)!=0 ){
@@ -68944,6 +71400,20 @@ SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int szNew){
return SQLITE_OK;
}
+/*
+** It is already known that pMem contains an unterminated string.
+** Add the zero terminator.
+*/
+static SQLITE_NOINLINE int vdbeMemAddTerminator(Mem *pMem){
+ if( sqlite3VdbeMemGrow(pMem, pMem->n+2, 1) ){
+ return SQLITE_NOMEM_BKPT;
+ }
+ pMem->z[pMem->n] = 0;
+ pMem->z[pMem->n+1] = 0;
+ pMem->flags |= MEM_Term;
+ return SQLITE_OK;
+}
+
/*
** Change pMem so that its MEM_Str or MEM_Blob value is stored in
** MEM.zMalloc, where it can be safely written.
@@ -68956,12 +71426,8 @@ SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem *pMem){
if( (pMem->flags & (MEM_Str|MEM_Blob))!=0 ){
if( ExpandBlob(pMem) ) return SQLITE_NOMEM;
if( pMem->szMalloc==0 || pMem->z!=pMem->zMalloc ){
- if( sqlite3VdbeMemGrow(pMem, pMem->n + 2, 1) ){
- return SQLITE_NOMEM_BKPT;
- }
- pMem->z[pMem->n] = 0;
- pMem->z[pMem->n+1] = 0;
- pMem->flags |= MEM_Term;
+ int rc = vdbeMemAddTerminator(pMem);
+ if( rc ) return rc;
}
}
pMem->flags &= ~MEM_Ephem;
@@ -69000,20 +71466,6 @@ SQLITE_PRIVATE int sqlite3VdbeMemExpandBlob(Mem *pMem){
}
#endif
-/*
-** It is already known that pMem contains an unterminated string.
-** Add the zero terminator.
-*/
-static SQLITE_NOINLINE int vdbeMemAddTerminator(Mem *pMem){
- if( sqlite3VdbeMemGrow(pMem, pMem->n+2, 1) ){
- return SQLITE_NOMEM_BKPT;
- }
- pMem->z[pMem->n] = 0;
- pMem->z[pMem->n+1] = 0;
- pMem->flags |= MEM_Term;
- return SQLITE_OK;
-}
-
/*
** Make sure the given Mem is \u0000 terminated.
*/
@@ -69088,26 +71540,24 @@ SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem *pMem, u8 enc, u8 bForce){
** otherwise.
*/
SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){
- int rc = SQLITE_OK;
- if( ALWAYS(pFunc && pFunc->xFinalize) ){
- sqlite3_context ctx;
- Mem t;
- assert( (pMem->flags & MEM_Null)!=0 || pFunc==pMem->u.pDef );
- assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
- memset(&ctx, 0, sizeof(ctx));
- memset(&t, 0, sizeof(t));
- t.flags = MEM_Null;
- t.db = pMem->db;
- ctx.pOut = &t;
- ctx.pMem = pMem;
- ctx.pFunc = pFunc;
- pFunc->xFinalize(&ctx); /* IMP: R-24505-23230 */
- assert( (pMem->flags & MEM_Dyn)==0 );
- if( pMem->szMalloc>0 ) sqlite3DbFree(pMem->db, pMem->zMalloc);
- memcpy(pMem, &t, sizeof(t));
- rc = ctx.isError;
- }
- return rc;
+ sqlite3_context ctx;
+ Mem t;
+ assert( pFunc!=0 );
+ assert( pFunc->xFinalize!=0 );
+ assert( (pMem->flags & MEM_Null)!=0 || pFunc==pMem->u.pDef );
+ assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
+ memset(&ctx, 0, sizeof(ctx));
+ memset(&t, 0, sizeof(t));
+ t.flags = MEM_Null;
+ t.db = pMem->db;
+ ctx.pOut = &t;
+ ctx.pMem = pMem;
+ ctx.pFunc = pFunc;
+ pFunc->xFinalize(&ctx); /* IMP: R-24505-23230 */
+ assert( (pMem->flags & MEM_Dyn)==0 );
+ if( pMem->szMalloc>0 ) sqlite3DbFreeNN(pMem->db, pMem->zMalloc);
+ memcpy(pMem, &t, sizeof(t));
+ return ctx.isError;
}
/*
@@ -69154,7 +71604,7 @@ static SQLITE_NOINLINE void vdbeMemClear(Mem *p){
vdbeMemClearExternAndSetNull(p);
}
if( p->szMalloc ){
- sqlite3DbFree(p->db, p->zMalloc);
+ sqlite3DbFreeNN(p->db, p->zMalloc);
p->szMalloc = 0;
}
p->z = 0;
@@ -69182,7 +71632,7 @@ SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p){
** If the double is out of range of a 64-bit signed integer then
** return the closest available 64-bit signed integer.
*/
-static i64 doubleToInt64(double r){
+static SQLITE_NOINLINE i64 doubleToInt64(double r){
#ifdef SQLITE_OMIT_FLOATING_POINT
/* When floating-point is omitted, double and int64 are the same thing */
return r;
@@ -69218,6 +71668,11 @@ static i64 doubleToInt64(double r){
**
** If pMem represents a string value, its encoding might be changed.
*/
+static SQLITE_NOINLINE i64 memIntValue(Mem *pMem){
+ i64 value = 0;
+ sqlite3Atoi64(pMem->z, &value, pMem->n, pMem->enc);
+ return value;
+}
SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem *pMem){
int flags;
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
@@ -69228,10 +71683,8 @@ SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem *pMem){
}else if( flags & MEM_Real ){
return doubleToInt64(pMem->u.r);
}else if( flags & (MEM_Str|MEM_Blob) ){
- i64 value = 0;
assert( pMem->z || pMem->n==0 );
- sqlite3Atoi64(pMem->z, &value, pMem->n, pMem->enc);
- return value;
+ return memIntValue(pMem);
}else{
return 0;
}
@@ -69243,6 +71696,12 @@ SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem *pMem){
** value. If it is a string or blob, try to convert it to a double.
** If it is a NULL, return 0.0.
*/
+static SQLITE_NOINLINE double memRealValue(Mem *pMem){
+ /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
+ double val = (double)0;
+ sqlite3AtoF(pMem->z, &val, pMem->n, pMem->enc);
+ return val;
+}
SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem *pMem){
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
@@ -69251,10 +71710,7 @@ SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem *pMem){
}else if( pMem->flags & MEM_Int ){
return (double)pMem->u.i;
}else if( pMem->flags & (MEM_Str|MEM_Blob) ){
- /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
- double val = (double)0;
- sqlite3AtoF(pMem->z, &val, pMem->n, pMem->enc);
- return val;
+ return memRealValue(pMem);
}else{
/* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
return (double)0;
@@ -69326,14 +71782,21 @@ SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem *pMem){
*/
SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem *pMem){
if( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))==0 ){
+ int rc;
assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
- if( 0==sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc) ){
+ rc = sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc);
+ if( rc==0 ){
MemSetTypeFlag(pMem, MEM_Int);
}else{
- pMem->u.r = sqlite3VdbeRealValue(pMem);
- MemSetTypeFlag(pMem, MEM_Real);
- sqlite3VdbeIntegerAffinity(pMem);
+ i64 i = pMem->u.i;
+ sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc);
+ if( rc==1 && pMem->u.r==(double)i ){
+ pMem->u.i = i;
+ MemSetTypeFlag(pMem, MEM_Int);
+ }else{
+ MemSetTypeFlag(pMem, MEM_Real);
+ }
}
}
assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))!=0 );
@@ -69459,6 +71922,27 @@ SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){
}
}
+/* A no-op destructor */
+static void sqlite3NoopDestructor(void *p){ UNUSED_PARAMETER(p); }
+
+/*
+** Set the value stored in *pMem should already be a NULL.
+** Also store a pointer to go with it.
+*/
+SQLITE_PRIVATE void sqlite3VdbeMemSetPointer(
+ Mem *pMem,
+ void *pPtr,
+ const char *zPType,
+ void (*xDestructor)(void*)
+){
+ assert( pMem->flags==MEM_Null );
+ pMem->u.zPType = zPType ? zPType : "";
+ pMem->z = pPtr;
+ pMem->flags = MEM_Null|MEM_Dyn|MEM_Subtype|MEM_Term;
+ pMem->eSubtype = 'p';
+ pMem->xDel = xDestructor ? xDestructor : sqlite3NoopDestructor;
+}
+
#ifndef SQLITE_OMIT_FLOATING_POINT
/*
** Delete any previous value and set the value stored in *pMem to val,
@@ -69639,7 +72123,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetStr(
if( nByte<0 ){
assert( enc!=0 );
if( enc==SQLITE_UTF8 ){
- nByte = sqlite3Strlen30(z);
+ nByte = 0x7fffffff & (int)strlen(z);
if( nByte>iLimit ) nByte = iLimit+1;
}else{
for(nByte=0; nByte<=iLimit && (z[nByte] | z[nByte+1]); nByte+=2){}
@@ -69696,10 +72180,9 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetStr(
/*
** Move data out of a btree key or data field and into a Mem structure.
-** The data or key is taken from the entry that pCur is currently pointing
+** The data is payload from the entry that pCur is currently pointing
** to. offset and amt determine what portion of the data or key to retrieve.
-** key is true to get the key or false to get data. The result is written
-** into the pMem element.
+** The result is written into the pMem element.
**
** The pMem object must have been initialized. This routine will use
** pMem->zMalloc to hold the content from the btree, if possible. New
@@ -69714,21 +72197,15 @@ static SQLITE_NOINLINE int vdbeMemFromBtreeResize(
BtCursor *pCur, /* Cursor pointing at record to retrieve. */
u32 offset, /* Offset from the start of data to return bytes from. */
u32 amt, /* Number of bytes to return. */
- int key, /* If true, retrieve from the btree key, not data. */
Mem *pMem /* OUT: Return data in this Mem structure. */
){
int rc;
pMem->flags = MEM_Null;
- if( SQLITE_OK==(rc = sqlite3VdbeMemClearAndResize(pMem, amt+2)) ){
- if( key ){
- rc = sqlite3BtreeKey(pCur, offset, amt, pMem->z);
- }else{
- rc = sqlite3BtreeData(pCur, offset, amt, pMem->z);
- }
+ if( SQLITE_OK==(rc = sqlite3VdbeMemClearAndResize(pMem, amt+1)) ){
+ rc = sqlite3BtreePayload(pCur, offset, amt, pMem->z);
if( rc==SQLITE_OK ){
- pMem->z[amt] = 0;
- pMem->z[amt+1] = 0;
- pMem->flags = MEM_Blob|MEM_Term;
+ pMem->z[amt] = 0; /* Overrun area used when reading malformed records */
+ pMem->flags = MEM_Blob;
pMem->n = (int)amt;
}else{
sqlite3VdbeMemRelease(pMem);
@@ -69740,7 +72217,6 @@ SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(
BtCursor *pCur, /* Cursor pointing at record to retrieve. */
u32 offset, /* Offset from the start of data to return bytes from. */
u32 amt, /* Number of bytes to return. */
- int key, /* If true, retrieve from the btree key, not data. */
Mem *pMem /* OUT: Return data in this Mem structure. */
){
char *zData; /* Data from the btree layer */
@@ -69761,7 +72237,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(
pMem->flags = MEM_Blob|MEM_Ephem;
pMem->n = (int)amt;
}else{
- rc = vdbeMemFromBtreeResize(pCur, offset, amt, key, pMem);
+ rc = vdbeMemFromBtreeResize(pCur, offset, amt, pMem);
}
return rc;
@@ -69779,6 +72255,7 @@ static SQLITE_NOINLINE const void *valueToText(sqlite3_value* pVal, u8 enc){
assert( (pVal->flags & MEM_RowSet)==0 );
assert( (pVal->flags & (MEM_Null))==0 );
if( pVal->flags & (MEM_Blob|MEM_Str) ){
+ if( ExpandBlob(pVal) ) return 0;
pVal->flags |= MEM_Str;
if( pVal->enc != (enc & ~SQLITE_UTF16_ALIGNED) ){
sqlite3VdbeChangeEncoding(pVal, enc & ~SQLITE_UTF16_ALIGNED);
@@ -69877,7 +72354,7 @@ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){
if( pRec ){
pRec->pKeyInfo = sqlite3KeyInfoOfIndex(p->pParse, pIdx);
if( pRec->pKeyInfo ){
- assert( pRec->pKeyInfo->nField+pRec->pKeyInfo->nXField==nCol );
+ assert( pRec->pKeyInfo->nAllField==nCol );
assert( pRec->pKeyInfo->enc==ENC(db) );
pRec->aMem = (Mem *)((u8*)pRec + ROUND8(sizeof(UnpackedRecord)));
for(i=0; iaMem[i].db = db;
}
}else{
- sqlite3DbFree(db, pRec);
+ sqlite3DbFreeNN(db, pRec);
pRec = 0;
}
}
@@ -69997,7 +72474,7 @@ static int valueFromFunction(
for(i=0; iop)==TK_UPLUS || op==TK_SPAN ) pExpr = pExpr->pLeft;
+#if defined(SQLITE_ENABLE_STAT3_OR_STAT4)
+ if( op==TK_REGISTER ) op = pExpr->op2;
+#else
if( NEVER(op==TK_REGISTER) ) op = pExpr->op2;
+#endif
/* Compressed expressions only appear when parsing the DEFAULT clause
** on a table column definition, and hence only when pCtx==0. This
@@ -70085,7 +72566,7 @@ static int valueFromExpr(
}
}else if( op==TK_UMINUS ) {
/* This branch happens for multiple negative signs. Ex: -(-5) */
- if( SQLITE_OK==sqlite3ValueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal)
+ if( SQLITE_OK==valueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal,pCtx)
&& pVal!=0
){
sqlite3VdbeMemNumerify(pVal);
@@ -70102,6 +72583,7 @@ static int valueFromExpr(
}else if( op==TK_NULL ){
pVal = valueNew(db, pCtx);
if( pVal==0 ) goto no_mem;
+ sqlite3VdbeMemNumerify(pVal);
}
#ifndef SQLITE_OMIT_BLOB_LITERAL
else if( op==TK_BLOB ){
@@ -70128,7 +72610,10 @@ static int valueFromExpr(
return rc;
no_mem:
- sqlite3OomFault(db);
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+ if( pCtx==0 || pCtx->pParse->nErr==0 )
+#endif
+ sqlite3OomFault(db);
sqlite3DbFree(db, zVal);
assert( *ppVal==0 );
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
@@ -70195,7 +72680,7 @@ static void recordFunc(
putVarint32(&aRet[1], iSerial);
sqlite3VdbeSerialPut(&aRet[1+nSerial], argv[0], iSerial);
sqlite3_result_blob(context, aRet, nRet, SQLITE_TRANSIENT);
- sqlite3DbFree(db, aRet);
+ sqlite3DbFreeNN(db, aRet);
}
}
@@ -70241,14 +72726,13 @@ static int stat4ValueFromExpr(
/* Skip over any TK_COLLATE nodes */
pExpr = sqlite3ExprSkipCollate(pExpr);
+ assert( pExpr==0 || pExpr->op!=TK_REGISTER || pExpr->op2!=TK_VARIABLE );
if( !pExpr ){
pVal = valueNew(db, pAlloc);
if( pVal ){
sqlite3VdbeMemSetNull((Mem*)pVal);
}
- }else if( pExpr->op==TK_VARIABLE
- || NEVER(pExpr->op==TK_REGISTER && pExpr->op2==TK_VARIABLE)
- ){
+ }else if( pExpr->op==TK_VARIABLE && (db->flags & SQLITE_EnableQPSG)==0 ){
Vdbe *v;
int iBindVar = pExpr->iColumn;
sqlite3VdbeSetVarmask(pParse->pVdbe, iBindVar);
@@ -70256,9 +72740,7 @@ static int stat4ValueFromExpr(
pVal = valueNew(db, pAlloc);
if( pVal ){
rc = sqlite3VdbeMemCopy((Mem*)pVal, &v->aVar[iBindVar-1]);
- if( rc==SQLITE_OK ){
- sqlite3ValueApplyAffinity(pVal, affinity, ENC(db));
- }
+ sqlite3ValueApplyAffinity(pVal, affinity, ENC(db));
pVal->db = pParse->db;
}
}
@@ -70415,14 +72897,14 @@ SQLITE_PRIVATE int sqlite3Stat4Column(
SQLITE_PRIVATE void sqlite3Stat4ProbeFree(UnpackedRecord *pRec){
if( pRec ){
int i;
- int nCol = pRec->pKeyInfo->nField+pRec->pKeyInfo->nXField;
+ int nCol = pRec->pKeyInfo->nAllField;
Mem *aMem = pRec->aMem;
sqlite3 *db = aMem[0].db;
for(i=0; ipKeyInfo);
- sqlite3DbFree(db, pRec);
+ sqlite3DbFreeNN(db, pRec);
}
}
#endif /* ifdef SQLITE_ENABLE_STAT4 */
@@ -70446,7 +72928,7 @@ SQLITE_PRIVATE void sqlite3ValueSetStr(
SQLITE_PRIVATE void sqlite3ValueFree(sqlite3_value *v){
if( !v ) return;
sqlite3VdbeMemRelease((Mem *)v);
- sqlite3DbFree(((Mem*)v)->db, v);
+ sqlite3DbFreeNN(((Mem*)v)->db, v);
}
/*
@@ -70511,10 +72993,12 @@ SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(Parse *pParse){
db->pVdbe = p;
p->magic = VDBE_MAGIC_INIT;
p->pParse = pParse;
+ pParse->pVdbe = p;
assert( pParse->aLabel==0 );
assert( pParse->nLabel==0 );
assert( pParse->nOpAlloc==0 );
assert( pParse->szOpAlloc==0 );
+ sqlite3VdbeAddOp2(p, OP_Init, 0, 1);
return p;
}
@@ -70532,15 +73016,14 @@ SQLITE_PRIVATE void sqlite3VdbeError(Vdbe *p, const char *zFormat, ...){
/*
** Remember the SQL string for a prepared statement.
*/
-SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, int isPrepareV2){
- assert( isPrepareV2==1 || isPrepareV2==0 );
+SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, u8 prepFlags){
if( p==0 ) return;
-#if defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_ENABLE_SQLLOG)
- if( !isPrepareV2 ) return;
-#endif
+ p->prepFlags = prepFlags;
+ if( (prepFlags & SQLITE_PREPARE_SAVESQL)==0 ){
+ p->expmask = 0;
+ }
assert( p->zSql==0 );
p->zSql = sqlite3DbStrNDup(p->db, z, n);
- p->isPrepareV2 = (u8)isPrepareV2;
}
/*
@@ -70562,7 +73045,10 @@ SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){
zTmp = pA->zSql;
pA->zSql = pB->zSql;
pB->zSql = zTmp;
- pB->isPrepareV2 = pA->isPrepareV2;
+ pB->expmask = pA->expmask;
+ pB->prepFlags = pA->prepFlags;
+ memcpy(pB->aCounter, pA->aCounter, sizeof(pB->aCounter));
+ pB->aCounter[SQLITE_STMTSTATUS_REPREPARE]++;
}
/*
@@ -70593,6 +73079,12 @@ static int growOpArray(Vdbe *v, int nOp){
UNUSED_PARAMETER(nOp);
#endif
+ /* Ensure that the size of a VDBE does not grow too large */
+ if( nNew > p->db->aLimit[SQLITE_LIMIT_VDBE_OP] ){
+ sqlite3OomFault(p->db);
+ return SQLITE_NOMEM;
+ }
+
assert( nOp<=(1024/sizeof(Op)) );
assert( nNew>=(p->nOpAlloc+nOp) );
pNew = sqlite3DbRealloc(p->db, v->aOp, nNew*sizeof(Op));
@@ -70712,6 +73204,9 @@ SQLITE_PRIVATE int sqlite3VdbeLoadString(Vdbe *p, int iDest, const char *zStr){
** "s" character in zTypes[], the register is a string if the argument is
** not NULL, or OP_Null if the value is a null pointer. For each "i" character
** in zTypes[], the register is initialized to an integer.
+**
+** If the input string does not end with "X" then an OP_ResultRow instruction
+** is generated for the values inserted.
*/
SQLITE_PRIVATE void sqlite3VdbeMultiLoad(Vdbe *p, int iDest, const char *zTypes, ...){
va_list ap;
@@ -70721,12 +73216,15 @@ SQLITE_PRIVATE void sqlite3VdbeMultiLoad(Vdbe *p, int iDest, const char *zTypes,
for(i=0; (c = zTypes[i])!=0; i++){
if( c=='s' ){
const char *z = va_arg(ap, const char*);
- sqlite3VdbeAddOp4(p, z==0 ? OP_Null : OP_String8, 0, iDest++, 0, z, 0);
+ sqlite3VdbeAddOp4(p, z==0 ? OP_Null : OP_String8, 0, iDest+i, 0, z, 0);
+ }else if( c=='i' ){
+ sqlite3VdbeAddOp2(p, OP_Integer, va_arg(ap, int), iDest+i);
}else{
- assert( c=='i' );
- sqlite3VdbeAddOp2(p, OP_Integer, va_arg(ap, int), iDest++);
+ goto skip_op_resultrow;
}
}
+ sqlite3VdbeAddOp2(p, OP_ResultRow, iDest, i);
+skip_op_resultrow:
va_end(ap);
}
@@ -70791,7 +73289,11 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(
int p4 /* The P4 operand as an integer */
){
int addr = sqlite3VdbeAddOp3(p, op, p1, p2, p3);
- sqlite3VdbeChangeP4(p, addr, SQLITE_INT_TO_PTR(p4), P4_INT32);
+ if( p->db->mallocFailed==0 ){
+ VdbeOp *pOp = &p->aOp[addr];
+ pOp->p4type = P4_INT32;
+ pOp->p4.i = p4;
+ }
return addr;
}
@@ -70950,7 +73452,8 @@ static Op *opIterNext(VdbeOpIter *p){
** * OP_VUpdate
** * OP_VRename
** * OP_FkCounter with P2==0 (immediate foreign key constraint)
-** * OP_CreateTable and OP_InitCoroutine (for CREATE TABLE AS SELECT ...)
+** * OP_CreateBtree/BTREE_INTKEY and OP_InitCoroutine
+** (for CREATE TABLE AS SELECT ...)
**
** Then check that the value of Parse.mayAbort is true if an
** ABORT may be thrown, or false otherwise. Return true if it does
@@ -70978,7 +73481,7 @@ SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
hasAbort = 1;
break;
}
- if( opcode==OP_CreateTable ) hasCreateTable = 1;
+ if( opcode==OP_CreateBtree && pOp->p3==BTREE_INTKEY ) hasCreateTable = 1;
if( opcode==OP_InitCoroutine ) hasInitCoroutine = 1;
#ifndef SQLITE_OMIT_FOREIGN_KEY
if( opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1 ){
@@ -71057,6 +73560,27 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
p->bIsReader = 1;
break;
}
+ case OP_Next:
+ case OP_NextIfOpen:
+ case OP_SorterNext: {
+ pOp->p4.xAdvance = sqlite3BtreeNext;
+ pOp->p4type = P4_ADVANCE;
+ /* The code generator never codes any of these opcodes as a jump
+ ** to a label. They are always coded as a jump backwards to a
+ ** known address */
+ assert( pOp->p2>=0 );
+ break;
+ }
+ case OP_Prev:
+ case OP_PrevIfOpen: {
+ pOp->p4.xAdvance = sqlite3BtreePrevious;
+ pOp->p4type = P4_ADVANCE;
+ /* The code generator never codes any of these opcodes as a jump
+ ** to a label. They are always coded as a jump backwards to a
+ ** known address */
+ assert( pOp->p2>=0 );
+ break;
+ }
#ifndef SQLITE_OMIT_VIRTUALTABLE
case OP_VUpdate: {
if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2;
@@ -71068,27 +73592,25 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
assert( pOp[-1].opcode==OP_Integer );
n = pOp[-1].p1;
if( n>nMaxArgs ) nMaxArgs = n;
- break;
+ /* Fall through into the default case */
}
#endif
- case OP_Next:
- case OP_NextIfOpen:
- case OP_SorterNext: {
- pOp->p4.xAdvance = sqlite3BtreeNext;
- pOp->p4type = P4_ADVANCE;
- break;
- }
- case OP_Prev:
- case OP_PrevIfOpen: {
- pOp->p4.xAdvance = sqlite3BtreePrevious;
- pOp->p4type = P4_ADVANCE;
+ default: {
+ if( pOp->p2<0 ){
+ /* The mkopcodeh.tcl script has so arranged things that the only
+ ** non-jump opcodes less than SQLITE_MX_JUMP_CODE are guaranteed to
+ ** have non-negative values for P2. */
+ assert( (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_JUMP)!=0 );
+ assert( ADDR(pOp->p2)nLabel );
+ pOp->p2 = aLabel[ADDR(pOp->p2)];
+ }
break;
}
}
- if( (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_JUMP)!=0 && pOp->p2<0 ){
- assert( ADDR(pOp->p2)nLabel );
- pOp->p2 = aLabel[ADDR(pOp->p2)];
- }
+ /* The mkopcodeh.tcl script has so arranged things that the only
+ ** non-jump opcodes less than SQLITE_MX_JUMP_CODE are guaranteed to
+ ** have non-negative values for P2. */
+ assert( (sqlite3OpcodeProperty[pOp->opcode]&OPFLG_JUMP)==0 || pOp->p2>=0);
}
if( pOp==p->aOp ) break;
pOp--;
@@ -71122,6 +73644,22 @@ SQLITE_PRIVATE void sqlite3VdbeVerifyNoMallocRequired(Vdbe *p, int N){
}
#endif
+/*
+** Verify that the VM passed as the only argument does not contain
+** an OP_ResultRow opcode. Fail an assert() if it does. This is used
+** by code in pragma.c to ensure that the implementation of certain
+** pragmas comports with the flags specified in the mkpragmatab.tcl
+** script.
+*/
+#if defined(SQLITE_DEBUG) && !defined(SQLITE_TEST_REALLOC_STRESS)
+SQLITE_PRIVATE void sqlite3VdbeVerifyNoResultRow(Vdbe *p){
+ int i;
+ for(i=0; inOp; i++){
+ assert( p->aOp[i].opcode!=OP_ResultRow );
+ }
+}
+#endif
+
/*
** This function returns a pointer to the array of opcodes associated with
** the Vdbe passed as the first argument. It is the callers responsibility
@@ -71241,7 +73779,7 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe *p, u32 addr, int val){
SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe *p, u32 addr, int val){
sqlite3VdbeGetOp(p,addr)->p3 = val;
}
-SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe *p, u8 p5){
+SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe *p, u16 p5){
assert( p->nOp>0 || p->db->mallocFailed );
if( p->nOp>0 ) p->aOp[p->nOp-1].p5 = p5;
}
@@ -71261,7 +73799,7 @@ SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe *p, int addr){
*/
static void freeEphemeralFunction(sqlite3 *db, FuncDef *pDef){
if( (pDef->funcFlags & SQLITE_FUNC_EPHEM)!=0 ){
- sqlite3DbFree(db, pDef);
+ sqlite3DbFreeNN(db, pDef);
}
}
@@ -71272,11 +73810,11 @@ static void vdbeFreeOpArray(sqlite3 *, Op *, int);
*/
static SQLITE_NOINLINE void freeP4Mem(sqlite3 *db, Mem *p){
if( p->szMalloc ) sqlite3DbFree(db, p->zMalloc);
- sqlite3DbFree(db, p);
+ sqlite3DbFreeNN(db, p);
}
static SQLITE_NOINLINE void freeP4FuncCtx(sqlite3 *db, sqlite3_context *p){
freeEphemeralFunction(db, p->pFunc);
- sqlite3DbFree(db, p);
+ sqlite3DbFreeNN(db, p);
}
static void freeP4(sqlite3 *db, int p4type, void *p4){
assert( db );
@@ -71288,6 +73826,7 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){
case P4_REAL:
case P4_INT64:
case P4_DYNAMIC:
+ case P4_DYNBLOB:
case P4_INTARRAY: {
sqlite3DbFree(db, p4);
break;
@@ -71302,10 +73841,6 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){
break;
}
#endif
- case P4_MPRINTF: {
- if( db->pnBytesFreed==0 ) sqlite3_free(p4);
- break;
- }
case P4_FUNCDEF: {
freeEphemeralFunction(db, (FuncDef*)p4);
break;
@@ -71333,14 +73868,14 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){
static void vdbeFreeOpArray(sqlite3 *db, Op *aOp, int nOp){
if( aOp ){
Op *pOp;
- for(pOp=aOp; pOp<&aOp[nOp]; pOp++){
- if( pOp->p4type ) freeP4(db, pOp->p4type, pOp->p4.p);
+ for(pOp=&aOp[nOp-1]; pOp>=aOp; pOp--){
+ if( pOp->p4type <= P4_FREE_IF_LE ) freeP4(db, pOp->p4type, pOp->p4.p);
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
sqlite3DbFree(db, pOp->zComment);
#endif
}
+ sqlite3DbFreeNN(db, aOp);
}
- sqlite3DbFree(db, aOp);
}
/*
@@ -71450,16 +73985,42 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int
}
}
+/*
+** Change the P4 operand of the most recently coded instruction
+** to the value defined by the arguments. This is a high-speed
+** version of sqlite3VdbeChangeP4().
+**
+** The P4 operand must not have been previously defined. And the new
+** P4 must not be P4_INT32. Use sqlite3VdbeChangeP4() in either of
+** those cases.
+*/
+SQLITE_PRIVATE void sqlite3VdbeAppendP4(Vdbe *p, void *pP4, int n){
+ VdbeOp *pOp;
+ assert( n!=P4_INT32 && n!=P4_VTAB );
+ assert( n<=0 );
+ if( p->db->mallocFailed ){
+ freeP4(p->db, n, pP4);
+ }else{
+ assert( pP4!=0 );
+ assert( p->nOp>0 );
+ pOp = &p->aOp[p->nOp-1];
+ assert( pOp->p4type==P4_NOTUSED );
+ pOp->p4type = n;
+ pOp->p4.p = pP4;
+ }
+}
+
/*
** Set the P4 on the most recently added opcode to the KeyInfo for the
** index given.
*/
SQLITE_PRIVATE void sqlite3VdbeSetP4KeyInfo(Parse *pParse, Index *pIdx){
Vdbe *v = pParse->pVdbe;
+ KeyInfo *pKeyInfo;
assert( v!=0 );
assert( pIdx!=0 );
- sqlite3VdbeChangeP4(v, -1, (char*)sqlite3KeyInfoOfIndex(pParse, pIdx),
- P4_KEYINFO);
+ pKeyInfo = sqlite3KeyInfoOfIndex(pParse, pIdx);
+ if( pKeyInfo ) sqlite3VdbeAppendP4(v, pKeyInfo, P4_KEYINFO);
}
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
@@ -71723,8 +74284,8 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
int j;
KeyInfo *pKeyInfo = pOp->p4.pKeyInfo;
assert( pKeyInfo->aSortOrder!=0 );
- sqlite3XPrintf(&x, "k(%d", pKeyInfo->nField);
- for(j=0; jnField; j++){
+ sqlite3XPrintf(&x, "k(%d", pKeyInfo->nKeyField);
+ for(j=0; jnKeyField; j++){
CollSeq *pColl = pKeyInfo->aColl[j];
const char *zColl = pColl ? pColl->zName : "";
if( strcmp(zColl, "BINARY")==0 ) zColl = "B";
@@ -71749,7 +74310,7 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
sqlite3XPrintf(&x, "%s(%d)", pDef->zName, pDef->nArg);
break;
}
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
case P4_FUNCCTX: {
FuncDef *pDef = pOp->p4.pCtx->pFunc;
sqlite3XPrintf(&x, "%s(%d)", pDef->zName, pDef->nArg);
@@ -71796,7 +74357,7 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
int *ai = pOp->p4.ai;
int n = ai[0]; /* The first element of an INTARRAY is always the
** count of the number of elements to follow */
- for(i=1; iflags&(MEM_Agg|MEM_Dyn|MEM_Frame|MEM_RowSet) ){
sqlite3VdbeMemRelease(p);
}else if( p->szMalloc ){
- sqlite3DbFree(db, p->zMalloc);
+ sqlite3DbFreeNN(db, p->zMalloc);
p->szMalloc = 0;
}
@@ -72039,6 +74601,8 @@ SQLITE_PRIVATE int sqlite3VdbeList(
int i; /* Loop counter */
int rc = SQLITE_OK; /* Return code */
Mem *pMem = &p->aMem[1]; /* First Mem of result set */
+ int bListSubprogs = (p->explain==1 || (db->flags & SQLITE_TriggerEQP)!=0);
+ Op *pOp = 0;
assert( p->explain );
assert( p->magic==VDBE_MAGIC_RUN );
@@ -72051,7 +74615,7 @@ SQLITE_PRIVATE int sqlite3VdbeList(
releaseMemArray(pMem, 8);
p->pResultSet = 0;
- if( p->rc==SQLITE_NOMEM_BKPT ){
+ if( p->rc==SQLITE_NOMEM ){
/* This happens if a malloc() inside a call to sqlite3_column_text() or
** sqlite3_column_text16() failed. */
sqlite3OomFault(db);
@@ -72066,7 +74630,7 @@ SQLITE_PRIVATE int sqlite3VdbeList(
** encountered, but p->pc will eventually catch up to nRow.
*/
nRow = p->nOp;
- if( p->explain==1 ){
+ if( bListSubprogs ){
/* The first 8 memory cells are used for the result set. So we will
** commandeer the 9th cell to use as storage for an array of pointers
** to trigger subprograms. The VDBE is guaranteed to have at least 9
@@ -72086,17 +74650,11 @@ SQLITE_PRIVATE int sqlite3VdbeList(
do{
i = p->pc++;
- }while( iexplain==2 && p->aOp[i].opcode!=OP_Explain );
- if( i>=nRow ){
- p->rc = SQLITE_OK;
- rc = SQLITE_DONE;
- }else if( db->u1.isInterrupted ){
- p->rc = SQLITE_INTERRUPT;
- rc = SQLITE_ERROR;
- sqlite3VdbeError(p, sqlite3ErrStr(p->rc));
- }else{
- char *zP4;
- Op *pOp;
+ if( i>=nRow ){
+ p->rc = SQLITE_OK;
+ rc = SQLITE_DONE;
+ break;
+ }
if( inOp ){
/* The output line number is small enough that we are still in the
** main program. */
@@ -72111,94 +74669,110 @@ SQLITE_PRIVATE int sqlite3VdbeList(
}
pOp = &apSub[j]->aOp[i];
}
- if( p->explain==1 ){
- pMem->flags = MEM_Int;
- pMem->u.i = i; /* Program counter */
- pMem++;
-
- pMem->flags = MEM_Static|MEM_Str|MEM_Term;
- pMem->z = (char*)sqlite3OpcodeName(pOp->opcode); /* Opcode */
- assert( pMem->z!=0 );
- pMem->n = sqlite3Strlen30(pMem->z);
- pMem->enc = SQLITE_UTF8;
- pMem++;
- /* When an OP_Program opcode is encounter (the only opcode that has
- ** a P4_SUBPROGRAM argument), expand the size of the array of subprograms
- ** kept in p->aMem[9].z to hold the new program - assuming this subprogram
- ** has not already been seen.
- */
- if( pOp->p4type==P4_SUBPROGRAM ){
- int nByte = (nSub+1)*sizeof(SubProgram*);
- int j;
- for(j=0; jp4.pProgram ) break;
- }
- if( j==nSub && SQLITE_OK==sqlite3VdbeMemGrow(pSub, nByte, nSub!=0) ){
- apSub = (SubProgram **)pSub->z;
- apSub[nSub++] = pOp->p4.pProgram;
- pSub->flags |= MEM_Blob;
- pSub->n = nSub*sizeof(SubProgram*);
+ /* When an OP_Program opcode is encounter (the only opcode that has
+ ** a P4_SUBPROGRAM argument), expand the size of the array of subprograms
+ ** kept in p->aMem[9].z to hold the new program - assuming this subprogram
+ ** has not already been seen.
+ */
+ if( bListSubprogs && pOp->p4type==P4_SUBPROGRAM ){
+ int nByte = (nSub+1)*sizeof(SubProgram*);
+ int j;
+ for(j=0; jp4.pProgram ) break;
+ }
+ if( j==nSub ){
+ p->rc = sqlite3VdbeMemGrow(pSub, nByte, nSub!=0);
+ if( p->rc!=SQLITE_OK ){
+ rc = SQLITE_ERROR;
+ break;
}
+ apSub = (SubProgram **)pSub->z;
+ apSub[nSub++] = pOp->p4.pProgram;
+ pSub->flags |= MEM_Blob;
+ pSub->n = nSub*sizeof(SubProgram*);
+ nRow += pOp->p4.pProgram->nOp;
}
}
+ }while( p->explain==2 && pOp->opcode!=OP_Explain );
- pMem->flags = MEM_Int;
- pMem->u.i = pOp->p1; /* P1 */
- pMem++;
+ if( rc==SQLITE_OK ){
+ if( db->u1.isInterrupted ){
+ p->rc = SQLITE_INTERRUPT;
+ rc = SQLITE_ERROR;
+ sqlite3VdbeError(p, sqlite3ErrStr(p->rc));
+ }else{
+ char *zP4;
+ if( p->explain==1 ){
+ pMem->flags = MEM_Int;
+ pMem->u.i = i; /* Program counter */
+ pMem++;
+
+ pMem->flags = MEM_Static|MEM_Str|MEM_Term;
+ pMem->z = (char*)sqlite3OpcodeName(pOp->opcode); /* Opcode */
+ assert( pMem->z!=0 );
+ pMem->n = sqlite3Strlen30(pMem->z);
+ pMem->enc = SQLITE_UTF8;
+ pMem++;
+ }
- pMem->flags = MEM_Int;
- pMem->u.i = pOp->p2; /* P2 */
- pMem++;
+ pMem->flags = MEM_Int;
+ pMem->u.i = pOp->p1; /* P1 */
+ pMem++;
- pMem->flags = MEM_Int;
- pMem->u.i = pOp->p3; /* P3 */
- pMem++;
+ pMem->flags = MEM_Int;
+ pMem->u.i = pOp->p2; /* P2 */
+ pMem++;
- if( sqlite3VdbeMemClearAndResize(pMem, 100) ){ /* P4 */
- assert( p->db->mallocFailed );
- return SQLITE_ERROR;
- }
- pMem->flags = MEM_Str|MEM_Term;
- zP4 = displayP4(pOp, pMem->z, pMem->szMalloc);
- if( zP4!=pMem->z ){
- pMem->n = 0;
- sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0);
- }else{
- assert( pMem->z!=0 );
- pMem->n = sqlite3Strlen30(pMem->z);
- pMem->enc = SQLITE_UTF8;
- }
- pMem++;
+ pMem->flags = MEM_Int;
+ pMem->u.i = pOp->p3; /* P3 */
+ pMem++;
- if( p->explain==1 ){
- if( sqlite3VdbeMemClearAndResize(pMem, 4) ){
+ if( sqlite3VdbeMemClearAndResize(pMem, 100) ){ /* P4 */
assert( p->db->mallocFailed );
return SQLITE_ERROR;
}
pMem->flags = MEM_Str|MEM_Term;
- pMem->n = 2;
- sqlite3_snprintf(3, pMem->z, "%.2x", pOp->p5); /* P5 */
- pMem->enc = SQLITE_UTF8;
+ zP4 = displayP4(pOp, pMem->z, pMem->szMalloc);
+ if( zP4!=pMem->z ){
+ pMem->n = 0;
+ sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0);
+ }else{
+ assert( pMem->z!=0 );
+ pMem->n = sqlite3Strlen30(pMem->z);
+ pMem->enc = SQLITE_UTF8;
+ }
pMem++;
-
+
+ if( p->explain==1 ){
+ if( sqlite3VdbeMemClearAndResize(pMem, 4) ){
+ assert( p->db->mallocFailed );
+ return SQLITE_ERROR;
+ }
+ pMem->flags = MEM_Str|MEM_Term;
+ pMem->n = 2;
+ sqlite3_snprintf(3, pMem->z, "%.2x", pOp->p5); /* P5 */
+ pMem->enc = SQLITE_UTF8;
+ pMem++;
+
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
- if( sqlite3VdbeMemClearAndResize(pMem, 500) ){
- assert( p->db->mallocFailed );
- return SQLITE_ERROR;
- }
- pMem->flags = MEM_Str|MEM_Term;
- pMem->n = displayComment(pOp, zP4, pMem->z, 500);
- pMem->enc = SQLITE_UTF8;
+ if( sqlite3VdbeMemClearAndResize(pMem, 500) ){
+ assert( p->db->mallocFailed );
+ return SQLITE_ERROR;
+ }
+ pMem->flags = MEM_Str|MEM_Term;
+ pMem->n = displayComment(pOp, zP4, pMem->z, 500);
+ pMem->enc = SQLITE_UTF8;
#else
- pMem->flags = MEM_Null; /* Comment */
+ pMem->flags = MEM_Null; /* Comment */
#endif
- }
+ }
- p->nResColumn = 8 - 4*(p->explain-1);
- p->pResultSet = &p->aMem[1];
- p->rc = SQLITE_OK;
- rc = SQLITE_ROW;
+ p->nResColumn = 8 - 4*(p->explain-1);
+ p->pResultSet = &p->aMem[1];
+ p->rc = SQLITE_OK;
+ rc = SQLITE_ROW;
+ }
}
return rc;
}
@@ -72427,10 +75001,8 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady(
x.nFree = x.nNeeded;
}while( !db->mallocFailed );
- p->nzVar = pParse->nzVar;
- p->azVar = pParse->azVar;
- pParse->nzVar = 0;
- pParse->azVar = 0;
+ p->pVList = pParse->pVList;
+ pParse->pVList = 0;
p->explain = pParse->explain;
if( db->mallocFailed ){
p->nVar = 0;
@@ -72458,15 +75030,15 @@ SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
if( pCx==0 ){
return;
}
- assert( pCx->pBt==0 || pCx->eCurType==CURTYPE_BTREE );
+ assert( pCx->pBtx==0 || pCx->eCurType==CURTYPE_BTREE );
switch( pCx->eCurType ){
case CURTYPE_SORTER: {
sqlite3VdbeSorterClose(p->db, pCx);
break;
}
case CURTYPE_BTREE: {
- if( pCx->pBt ){
- sqlite3BtreeClose(pCx->pBt);
+ if( pCx->isEphemeral ){
+ if( pCx->pBtx ) sqlite3BtreeClose(pCx->pBtx);
/* The pCx->pCursor will be close automatically, if it exists, by
** the call above. */
}else{
@@ -72562,27 +75134,6 @@ static void closeAllCursors(Vdbe *p){
assert( p->pAuxData==0 );
}
-/*
-** Clean up the VM after a single run.
-*/
-static void Cleanup(Vdbe *p){
- sqlite3 *db = p->db;
-
-#ifdef SQLITE_DEBUG
- /* Execute assert() statements to ensure that the Vdbe.apCsr[] and
- ** Vdbe.aMem[] arrays have already been cleaned up. */
- int i;
- if( p->apCsr ) for(i=0; inCursor; i++) assert( p->apCsr[i]==0 );
- if( p->aMem ){
- for(i=0; inMem; i++) assert( p->aMem[i].flags==MEM_Undefined );
- }
-#endif
-
- sqlite3DbFree(db, p->zErrMsg);
- p->zErrMsg = 0;
- p->pResultSet = 0;
-}
-
/*
** Set the number of result columns that will be returned by this SQL
** statement. This is now set at compile time, rather than during
@@ -72590,17 +75141,18 @@ static void Cleanup(Vdbe *p){
** be called on an SQL statement before sqlite3_step().
*/
SQLITE_PRIVATE void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){
- Mem *pColName;
int n;
sqlite3 *db = p->db;
- releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
- sqlite3DbFree(db, p->aColName);
+ if( p->nResColumn ){
+ releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
+ sqlite3DbFree(db, p->aColName);
+ }
n = nResColumn*COLNAME_N;
p->nResColumn = (u16)nResColumn;
- p->aColName = pColName = (Mem*)sqlite3DbMallocRawNN(db, sizeof(Mem)*n );
+ p->aColName = (Mem*)sqlite3DbMallocRawNN(db, sizeof(Mem)*n );
if( p->aColName==0 ) return;
- initMemArray(p->aColName, n, p->db, MEM_Null);
+ initMemArray(p->aColName, n, db, MEM_Null);
}
/*
@@ -72690,6 +75242,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
pPager = sqlite3BtreePager(pBt);
if( db->aDb[i].safety_level!=PAGER_SYNCHRONOUS_OFF
&& aMJNeeded[sqlite3PagerGetJournalMode(pPager)]
+ && sqlite3PagerIsMemdb(pPager)==0
){
assert( i!=1 );
nTrans++;
@@ -72935,60 +75488,59 @@ static void checkActiveVdbeCnt(sqlite3 *db){
** If an IO error occurs, an SQLITE_IOERR_XXX error code is returned.
** Otherwise SQLITE_OK.
*/
-SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){
+static SQLITE_NOINLINE int vdbeCloseStatement(Vdbe *p, int eOp){
sqlite3 *const db = p->db;
int rc = SQLITE_OK;
+ int i;
+ const int iSavepoint = p->iStatement-1;
- /* If p->iStatement is greater than zero, then this Vdbe opened a
- ** statement transaction that should be closed here. The only exception
- ** is that an IO error may have occurred, causing an emergency rollback.
- ** In this case (db->nStatement==0), and there is nothing to do.
- */
- if( db->nStatement && p->iStatement ){
- int i;
- const int iSavepoint = p->iStatement-1;
-
- assert( eOp==SAVEPOINT_ROLLBACK || eOp==SAVEPOINT_RELEASE);
- assert( db->nStatement>0 );
- assert( p->iStatement==(db->nStatement+db->nSavepoint) );
-
- for(i=0; inDb; i++){
- int rc2 = SQLITE_OK;
- Btree *pBt = db->aDb[i].pBt;
- if( pBt ){
- if( eOp==SAVEPOINT_ROLLBACK ){
- rc2 = sqlite3BtreeSavepoint(pBt, SAVEPOINT_ROLLBACK, iSavepoint);
- }
- if( rc2==SQLITE_OK ){
- rc2 = sqlite3BtreeSavepoint(pBt, SAVEPOINT_RELEASE, iSavepoint);
- }
- if( rc==SQLITE_OK ){
- rc = rc2;
- }
- }
- }
- db->nStatement--;
- p->iStatement = 0;
+ assert( eOp==SAVEPOINT_ROLLBACK || eOp==SAVEPOINT_RELEASE);
+ assert( db->nStatement>0 );
+ assert( p->iStatement==(db->nStatement+db->nSavepoint) );
- if( rc==SQLITE_OK ){
+ for(i=0; inDb; i++){
+ int rc2 = SQLITE_OK;
+ Btree *pBt = db->aDb[i].pBt;
+ if( pBt ){
if( eOp==SAVEPOINT_ROLLBACK ){
- rc = sqlite3VtabSavepoint(db, SAVEPOINT_ROLLBACK, iSavepoint);
+ rc2 = sqlite3BtreeSavepoint(pBt, SAVEPOINT_ROLLBACK, iSavepoint);
+ }
+ if( rc2==SQLITE_OK ){
+ rc2 = sqlite3BtreeSavepoint(pBt, SAVEPOINT_RELEASE, iSavepoint);
}
if( rc==SQLITE_OK ){
- rc = sqlite3VtabSavepoint(db, SAVEPOINT_RELEASE, iSavepoint);
+ rc = rc2;
}
}
+ }
+ db->nStatement--;
+ p->iStatement = 0;
- /* If the statement transaction is being rolled back, also restore the
- ** database handles deferred constraint counter to the value it had when
- ** the statement transaction was opened. */
+ if( rc==SQLITE_OK ){
if( eOp==SAVEPOINT_ROLLBACK ){
- db->nDeferredCons = p->nStmtDefCons;
- db->nDeferredImmCons = p->nStmtDefImmCons;
+ rc = sqlite3VtabSavepoint(db, SAVEPOINT_ROLLBACK, iSavepoint);
}
+ if( rc==SQLITE_OK ){
+ rc = sqlite3VtabSavepoint(db, SAVEPOINT_RELEASE, iSavepoint);
+ }
+ }
+
+ /* If the statement transaction is being rolled back, also restore the
+ ** database handles deferred constraint counter to the value it had when
+ ** the statement transaction was opened. */
+ if( eOp==SAVEPOINT_ROLLBACK ){
+ db->nDeferredCons = p->nStmtDefCons;
+ db->nDeferredImmCons = p->nStmtDefImmCons;
}
return rc;
}
+SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){
+ if( p->db->nStatement && p->iStatement ){
+ return vdbeCloseStatement(p, eOp);
+ }
+ return SQLITE_OK;
+}
+
/*
** This function is called when a transaction opened by the database
@@ -73048,13 +75600,13 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
** one, or the complete transaction if there is no statement transaction.
*/
+ if( p->magic!=VDBE_MAGIC_RUN ){
+ return SQLITE_OK;
+ }
if( db->mallocFailed ){
p->rc = SQLITE_NOMEM_BKPT;
}
closeAllCursors(p);
- if( p->magic!=VDBE_MAGIC_RUN ){
- return SQLITE_OK;
- }
checkActiveVdbeCnt(db);
/* No commit or rollback needed if the program never started or if the
@@ -73251,10 +75803,10 @@ SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p){
sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT);
sqlite3EndBenignMalloc();
db->bBenignMalloc--;
- db->errCode = rc;
- }else{
- sqlite3Error(db, rc);
+ }else if( db->pErr ){
+ sqlite3ValueSetNull(db->pErr);
}
+ db->errCode = rc;
return rc;
}
@@ -73291,6 +75843,10 @@ static void vdbeInvokeSqllog(Vdbe *v){
** VDBE_MAGIC_INIT.
*/
SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){
+#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
+ int i;
+#endif
+
sqlite3 *db;
db = p->db;
@@ -73308,8 +75864,6 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){
if( p->pc>=0 ){
vdbeInvokeSqllog(p);
sqlite3VdbeTransferError(p);
- sqlite3DbFree(db, p->zErrMsg);
- p->zErrMsg = 0;
if( p->runOnlyOnce ) p->expired = 1;
}else if( p->rc && p->expired ){
/* The expired flag was set on the VDBE before the first call
@@ -73317,13 +75871,21 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){
** called), set the database error in this case as well.
*/
sqlite3ErrorWithMsg(db, p->rc, p->zErrMsg ? "%s" : 0, p->zErrMsg);
- sqlite3DbFree(db, p->zErrMsg);
- p->zErrMsg = 0;
}
- /* Reclaim all memory used by the VDBE
+ /* Reset register contents and reclaim error message memory.
*/
- Cleanup(p);
+#ifdef SQLITE_DEBUG
+ /* Execute assert() statements to ensure that the Vdbe.apCsr[] and
+ ** Vdbe.aMem[] arrays have already been cleaned up. */
+ if( p->apCsr ) for(i=0; inCursor; i++) assert( p->apCsr[i]==0 );
+ if( p->aMem ){
+ for(i=0; inMem; i++) assert( p->aMem[i].flags==MEM_Undefined );
+ }
+#endif
+ sqlite3DbFree(db, p->zErrMsg);
+ p->zErrMsg = 0;
+ p->pResultSet = 0;
/* Save profiling information from this VDBE run.
*/
@@ -73331,7 +75893,6 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){
{
FILE *out = fopen("vdbe_profile.out", "a");
if( out ){
- int i;
fprintf(out, "---- ");
for(i=0; inOp; i++){
fprintf(out, "%02x", p->aOp[i].opcode);
@@ -73361,7 +75922,6 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){
}
}
#endif
- p->iCurrentTime = 0;
p->magic = VDBE_MAGIC_RESET;
return p->rc & db->errMask;
}
@@ -73400,16 +75960,18 @@ SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(sqlite3 *db, AuxData **pp, int iOp,
while( *pp ){
AuxData *pAux = *pp;
if( (iOp<0)
- || (pAux->iOp==iOp && (pAux->iArg>31 || !(mask & MASKBIT32(pAux->iArg))))
+ || (pAux->iAuxOp==iOp
+ && pAux->iAuxArg>=0
+ && (pAux->iAuxArg>31 || !(mask & MASKBIT32(pAux->iAuxArg))))
){
- testcase( pAux->iArg==31 );
- if( pAux->xDelete ){
- pAux->xDelete(pAux->pAux);
+ testcase( pAux->iAuxArg==31 );
+ if( pAux->xDeleteAux ){
+ pAux->xDeleteAux(pAux->pAux);
}
- *pp = pAux->pNext;
+ *pp = pAux->pNextAux;
sqlite3DbFree(db, pAux);
}else{
- pp= &pAux->pNext;
+ pp= &pAux->pNextAux;
}
}
}
@@ -73424,7 +75986,6 @@ SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(sqlite3 *db, AuxData **pp, int iOp,
*/
SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){
SubProgram *pSub, *pNext;
- int i;
assert( p->db==0 || p->db==db );
releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
for(pSub=p->pProgram; pSub; pSub=pNext){
@@ -73434,18 +75995,20 @@ SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){
}
if( p->magic!=VDBE_MAGIC_INIT ){
releaseMemArray(p->aVar, p->nVar);
- for(i=p->nzVar-1; i>=0; i--) sqlite3DbFree(db, p->azVar[i]);
- sqlite3DbFree(db, p->azVar);
+ sqlite3DbFree(db, p->pVList);
sqlite3DbFree(db, p->pFree);
}
vdbeFreeOpArray(db, p->aOp, p->nOp);
sqlite3DbFree(db, p->aColName);
sqlite3DbFree(db, p->zSql);
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
- for(i=0; inScan; i++){
- sqlite3DbFree(db, p->aScan[i].zName);
+ {
+ int i;
+ for(i=0; inScan; i++){
+ sqlite3DbFree(db, p->aScan[i].zName);
+ }
+ sqlite3DbFree(db, p->aScan);
}
- sqlite3DbFree(db, p->aScan);
#endif
}
@@ -73455,7 +76018,7 @@ SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){
SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){
sqlite3 *db;
- if( NEVER(p==0) ) return;
+ assert( p!=0 );
db = p->db;
assert( sqlite3_mutex_held(db->mutex) );
sqlite3VdbeClearObject(db, p);
@@ -73470,7 +76033,7 @@ SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){
}
p->magic = VDBE_MAGIC_DEAD;
p->db = 0;
- sqlite3DbFree(db, p);
+ sqlite3DbFreeNN(db, p);
}
/*
@@ -73542,19 +76105,18 @@ SQLITE_PRIVATE int sqlite3VdbeCursorRestore(VdbeCursor *p){
*/
SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor **pp, int *piCol){
VdbeCursor *p = *pp;
- if( p->eCurType==CURTYPE_BTREE ){
- if( p->deferredMoveto ){
- int iMap;
- if( p->aAltMap && (iMap = p->aAltMap[1+*piCol])>0 ){
- *pp = p->pAltCursor;
- *piCol = iMap - 1;
- return SQLITE_OK;
- }
- return handleDeferredMoveto(p);
- }
- if( sqlite3BtreeCursorHasMoved(p->uc.pCursor) ){
- return handleMovedCursor(p);
+ assert( p->eCurType==CURTYPE_BTREE || p->eCurType==CURTYPE_PSEUDO );
+ if( p->deferredMoveto ){
+ int iMap;
+ if( p->aAltMap && (iMap = p->aAltMap[1+*piCol])>0 ){
+ *pp = p->pAltCursor;
+ *piCol = iMap - 1;
+ return SQLITE_OK;
}
+ return handleDeferredMoveto(p);
+ }
+ if( sqlite3BtreeCursorHasMoved(p->uc.pCursor) ){
+ return handleMovedCursor(p);
}
return SQLITE_OK;
}
@@ -73852,7 +76414,13 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(
Mem *pMem /* Memory cell to write value into */
){
switch( serial_type ){
- case 10: /* Reserved for future use */
+ case 10: { /* Internal use only: NULL with virtual table
+ ** UPDATE no-change flag set */
+ pMem->flags = MEM_Null|MEM_Zero;
+ pMem->n = 0;
+ pMem->u.nZero = 0;
+ break;
+ }
case 11: /* Reserved for future use */
case 0: { /* Null */
/* EVIDENCE-OF: R-24078-09375 Value is a NULL. */
@@ -73946,34 +76514,17 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(
** If an OOM error occurs, NULL is returned.
*/
SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(
- KeyInfo *pKeyInfo, /* Description of the record */
- char *pSpace, /* Unaligned space available */
- int szSpace, /* Size of pSpace[] in bytes */
- char **ppFree /* OUT: Caller should free this pointer */
+ KeyInfo *pKeyInfo /* Description of the record */
){
UnpackedRecord *p; /* Unpacked record to return */
- int nOff; /* Increment pSpace by nOff to align it */
int nByte; /* Number of bytes required for *p */
-
- /* We want to shift the pointer pSpace up such that it is 8-byte aligned.
- ** Thus, we need to calculate a value, nOff, between 0 and 7, to shift
- ** it by. If pSpace is already 8-byte aligned, nOff should be zero.
- */
- nOff = (8 - (SQLITE_PTR_TO_INT(pSpace) & 7)) & 7;
- nByte = ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nField+1);
- if( nByte>szSpace+nOff ){
- p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte);
- *ppFree = (char *)p;
- if( !p ) return 0;
- }else{
- p = (UnpackedRecord*)&pSpace[nOff];
- *ppFree = 0;
- }
-
+ nByte = ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nKeyField+1);
+ p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte);
+ if( !p ) return 0;
p->aMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))];
assert( pKeyInfo->aSortOrder!=0 );
p->pKeyInfo = pKeyInfo;
- p->nField = pKeyInfo->nField + 1;
+ p->nField = pKeyInfo->nKeyField + 1;
return p;
}
@@ -74013,11 +76564,11 @@ SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(
pMem++;
if( (++u)>=p->nField ) break;
}
- assert( u<=pKeyInfo->nField + 1 );
+ assert( u<=pKeyInfo->nKeyField + 1 );
p->nField = u;
}
-#if SQLITE_DEBUG
+#ifdef SQLITE_DEBUG
/*
** This function compares two index or table record keys in the same way
** as the sqlite3VdbeRecordCompare() routine. Unlike VdbeRecordCompare(),
@@ -74062,9 +76613,9 @@ static int vdbeRecordCompareDebug(
idx1 = getVarint32(aKey1, szHdr1);
if( szHdr1>98307 ) return SQLITE_CORRUPT;
d1 = szHdr1;
- assert( pKeyInfo->nField+pKeyInfo->nXField>=pPKey2->nField || CORRUPT_DB );
+ assert( pKeyInfo->nAllField>=pPKey2->nField || CORRUPT_DB );
assert( pKeyInfo->aSortOrder!=0 );
- assert( pKeyInfo->nField>0 );
+ assert( pKeyInfo->nKeyField>0 );
assert( idx1<=szHdr1 || CORRUPT_DB );
do{
u32 serial_type1;
@@ -74122,16 +76673,16 @@ static int vdbeRecordCompareDebug(
}
#endif
-#if SQLITE_DEBUG
+#ifdef SQLITE_DEBUG
/*
** Count the number of fields (a.k.a. columns) in the record given by
** pKey,nKey. The verify that this count is less than or equal to the
-** limit given by pKeyInfo->nField + pKeyInfo->nXField.
+** limit given by pKeyInfo->nAllField.
**
** If this constraint is not satisfied, it means that the high-speed
** vdbeRecordCompareInt() and vdbeRecordCompareString() routines will
** not work correctly. If this assert() ever fires, it probably means
-** that the KeyInfo.nField or KeyInfo.nXField values were computed
+** that the KeyInfo.nKeyField or KeyInfo.nAllField values were computed
** incorrectly.
*/
static void vdbeAssertFieldCountWithinLimits(
@@ -74152,7 +76703,7 @@ static void vdbeAssertFieldCountWithinLimits(
idx += getVarint32(aKey+idx, notUsed);
nField++;
}
- assert( nField <= pKeyInfo->nField+pKeyInfo->nXField );
+ assert( nField <= pKeyInfo->nAllField );
}
#else
# define vdbeAssertFieldCountWithinLimits(A,B,C)
@@ -74177,7 +76728,6 @@ static int vdbeCompareMemString(
}else{
int rc;
const void *v1, *v2;
- int n1, n2;
Mem c1;
Mem c2;
sqlite3VdbeMemInit(&c1, pMem1->db, MEM_Null);
@@ -74185,11 +76735,13 @@ static int vdbeCompareMemString(
sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem);
sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem);
v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc);
- n1 = v1==0 ? 0 : c1.n;
v2 = sqlite3ValueText((sqlite3_value*)&c2, pColl->enc);
- n2 = v2==0 ? 0 : c2.n;
- rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2);
- if( (v1==0 || v2==0) && prcErr ) *prcErr = SQLITE_NOMEM_BKPT;
+ if( (v1==0 || v2==0) ){
+ if( prcErr ) *prcErr = SQLITE_NOMEM_BKPT;
+ rc = 0;
+ }else{
+ rc = pColl->xCmp(pColl->pUser, c1.n, v1, c2.n, v2);
+ }
sqlite3VdbeMemRelease(&c1);
sqlite3VdbeMemRelease(&c2);
return rc;
@@ -74456,10 +77008,10 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(
}
VVA_ONLY( mem1.szMalloc = 0; ) /* Only needed by assert() statements */
- assert( pPKey2->pKeyInfo->nField+pPKey2->pKeyInfo->nXField>=pPKey2->nField
+ assert( pPKey2->pKeyInfo->nAllField>=pPKey2->nField
|| CORRUPT_DB );
assert( pPKey2->pKeyInfo->aSortOrder!=0 );
- assert( pPKey2->pKeyInfo->nField>0 );
+ assert( pPKey2->pKeyInfo->nKeyField>0 );
assert( idx1<=szHdr1 || CORRUPT_DB );
do{
u32 serial_type;
@@ -74792,7 +77344,7 @@ SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *p){
** The easiest way to enforce this limit is to consider only records with
** 13 fields or less. If the first field is an integer, the maximum legal
** header size is (12*5 + 1 + 1) bytes. */
- if( (p->pKeyInfo->nField + p->pKeyInfo->nXField)<=13 ){
+ if( p->pKeyInfo->nAllField<=13 ){
int flags = p->aMem[0].flags;
if( p->pKeyInfo->aSortOrder[0] ){
p->r1 = 1;
@@ -74843,7 +77395,7 @@ SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3 *db, BtCursor *pCur, i64 *rowid){
/* Read in the complete content of the index entry */
sqlite3VdbeMemInit(&m, db, 0);
- rc = sqlite3VdbeMemFromBtree(pCur, 0, (u32)nCellKey, 1, &m);
+ rc = sqlite3VdbeMemFromBtree(pCur, 0, (u32)nCellKey, &m);
if( rc ){
return rc;
}
@@ -74923,7 +77475,7 @@ SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(
return SQLITE_CORRUPT_BKPT;
}
sqlite3VdbeMemInit(&m, db, 0);
- rc = sqlite3VdbeMemFromBtree(pCur, 0, (u32)nCellKey, 1, &m);
+ rc = sqlite3VdbeMemFromBtree(pCur, 0, (u32)nCellKey, &m);
if( rc ){
return rc;
}
@@ -74974,6 +77526,13 @@ SQLITE_PRIVATE sqlite3 *sqlite3VdbeDb(Vdbe *v){
return v->db;
}
+/*
+** Return the SQLITE_PREPARE flags for a Vdbe.
+*/
+SQLITE_PRIVATE u8 sqlite3VdbePrepareFlags(Vdbe *v){
+ return v->prepFlags;
+}
+
/*
** Return a pointer to an sqlite3_value structure containing the value bound
** parameter iVar of VM v. Except, if the value is an SQL NULL, return
@@ -74986,6 +77545,7 @@ SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe *v, int iVar, u8 aff
assert( iVar>0 );
if( v ){
Mem *pMem = &v->aVar[iVar-1];
+ assert( (v->db->flags & SQLITE_EnableQPSG)==0 );
if( 0==(pMem->flags & MEM_Null) ){
sqlite3_value *pRet = sqlite3ValueNew(v->db);
if( pRet ){
@@ -75005,13 +77565,36 @@ SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe *v, int iVar, u8 aff
*/
SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){
assert( iVar>0 );
- if( iVar>32 ){
- v->expmask = 0xffffffff;
+ assert( (v->db->flags & SQLITE_EnableQPSG)==0 );
+ if( iVar>=32 ){
+ v->expmask |= 0x80000000;
}else{
v->expmask |= ((u32)1 << (iVar-1));
}
}
+/*
+** Cause a function to throw an error if it was call from OP_PureFunc
+** rather than OP_Function.
+**
+** OP_PureFunc means that the function must be deterministic, and should
+** throw an error if it is given inputs that would make it non-deterministic.
+** This routine is invoked by date/time functions that use non-deterministic
+** features such as 'now'.
+*/
+SQLITE_PRIVATE int sqlite3NotPureFunc(sqlite3_context *pCtx){
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+ if( pCtx->pVdbe==0 ) return 1;
+#endif
+ if( pCtx->pVdbe->aOp[pCtx->iOp].opcode==OP_PureFunc ){
+ sqlite3_result_error(pCtx,
+ "non-deterministic function in index expression or CHECK constraint",
+ -1);
+ return 0;
+ }
+ return 1;
+}
+
#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
** Transfer error message text from an sqlite3_vtab.zErrMsg (text stored
@@ -75039,14 +77622,14 @@ SQLITE_PRIVATE void sqlite3VtabImportErrmsg(Vdbe *p, sqlite3_vtab *pVtab){
** This function is used to free UnpackedRecord structures allocated by
** the vdbeUnpackRecord() function found in vdbeapi.c.
*/
-static void vdbeFreeUnpacked(sqlite3 *db, UnpackedRecord *p){
+static void vdbeFreeUnpacked(sqlite3 *db, int nField, UnpackedRecord *p){
if( p ){
int i;
- for(i=0; inField; i++){
+ for(i=0; iaMem[i];
if( pMem->zMalloc ) sqlite3VdbeMemRelease(pMem);
}
- sqlite3DbFree(db, p);
+ sqlite3DbFreeNN(db, p);
}
}
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
@@ -75075,10 +77658,15 @@ SQLITE_PRIVATE void sqlite3VdbePreUpdateHook(
assert( db->pPreUpdate==0 );
memset(&preupdate, 0, sizeof(PreUpdate));
- if( op==SQLITE_UPDATE ){
- iKey2 = v->aMem[iReg].u.i;
+ if( HasRowid(pTab)==0 ){
+ iKey1 = iKey2 = 0;
+ preupdate.pPk = sqlite3PrimaryKeyIndex(pTab);
}else{
- iKey2 = iKey1;
+ if( op==SQLITE_UPDATE ){
+ iKey2 = v->aMem[iReg].u.i;
+ }else{
+ iKey2 = iKey1;
+ }
}
assert( pCsr->nField==pTab->nCol
@@ -75091,7 +77679,7 @@ SQLITE_PRIVATE void sqlite3VdbePreUpdateHook(
preupdate.iNewReg = iReg;
preupdate.keyinfo.db = db;
preupdate.keyinfo.enc = ENC(db);
- preupdate.keyinfo.nField = pTab->nCol;
+ preupdate.keyinfo.nKeyField = pTab->nCol;
preupdate.keyinfo.aSortOrder = (u8*)&fakeSortOrder;
preupdate.iKey1 = iKey1;
preupdate.iKey2 = iKey2;
@@ -75101,14 +77689,14 @@ SQLITE_PRIVATE void sqlite3VdbePreUpdateHook(
db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2);
db->pPreUpdate = 0;
sqlite3DbFree(db, preupdate.aRecord);
- vdbeFreeUnpacked(db, preupdate.pUnpacked);
- vdbeFreeUnpacked(db, preupdate.pNewUnpacked);
+ vdbeFreeUnpacked(db, preupdate.keyinfo.nKeyField+1, preupdate.pUnpacked);
+ vdbeFreeUnpacked(db, preupdate.keyinfo.nKeyField+1, preupdate.pNewUnpacked);
if( preupdate.aNew ){
int i;
for(i=0; inField; i++){
sqlite3VdbeMemRelease(&preupdate.aNew[i]);
}
- sqlite3DbFree(db, preupdate.aNew);
+ sqlite3DbFreeNN(db, preupdate.aNew);
}
}
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
@@ -75271,7 +77859,8 @@ SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt *pStmt){
sqlite3VdbeMemRelease(&p->aVar[i]);
p->aVar[i].flags = MEM_Null;
}
- if( p->isPrepareV2 && p->expmask ){
+ assert( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 || p->expmask==0 );
+ if( p->expmask ){
p->expired = 1;
}
sqlite3_mutex_leave(mutex);
@@ -75315,6 +77904,19 @@ SQLITE_API unsigned int sqlite3_value_subtype(sqlite3_value *pVal){
Mem *pMem = (Mem*)pVal;
return ((pMem->flags & MEM_Subtype) ? pMem->eSubtype : 0);
}
+SQLITE_API void *sqlite3_value_pointer(sqlite3_value *pVal, const char *zPType){
+ Mem *p = (Mem*)pVal;
+ if( (p->flags&(MEM_TypeMask|MEM_Term|MEM_Subtype)) ==
+ (MEM_Null|MEM_Term|MEM_Subtype)
+ && zPType!=0
+ && p->eSubtype=='p'
+ && strcmp(p->u.zPType, zPType)==0
+ ){
+ return (void*)p->z;
+ }else{
+ return 0;
+ }
+}
SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value *pVal){
return (const unsigned char *)sqlite3ValueText(pVal, SQLITE_UTF8);
}
@@ -75371,6 +77973,11 @@ SQLITE_API int sqlite3_value_type(sqlite3_value* pVal){
return aType[pVal->flags&MEM_AffMask];
}
+/* Return true if a parameter to xUpdate represents an unchanged column */
+SQLITE_API int sqlite3_value_nochange(sqlite3_value *pVal){
+ return (pVal->flags&(MEM_Null|MEM_Zero))==(MEM_Null|MEM_Zero);
+}
+
/* Make a copy of an sqlite3_value object
*/
SQLITE_API sqlite3_value *sqlite3_value_dup(const sqlite3_value *pOrig){
@@ -75493,6 +78100,18 @@ SQLITE_API void sqlite3_result_null(sqlite3_context *pCtx){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
sqlite3VdbeMemSetNull(pCtx->pOut);
}
+SQLITE_API void sqlite3_result_pointer(
+ sqlite3_context *pCtx,
+ void *pPtr,
+ const char *zPType,
+ void (*xDestructor)(void*)
+){
+ Mem *pOut = pCtx->pOut;
+ assert( sqlite3_mutex_held(pOut->db->mutex) );
+ sqlite3VdbeMemRelease(pOut);
+ pOut->flags = MEM_Null;
+ sqlite3VdbeMemSetPointer(pOut, pPtr, zPType, xDestructor);
+}
SQLITE_API void sqlite3_result_subtype(sqlite3_context *pCtx, unsigned int eSubtype){
Mem *pOut = pCtx->pOut;
assert( sqlite3_mutex_held(pOut->db->mutex) );
@@ -75615,7 +78234,7 @@ static int doWalCallbacks(sqlite3 *db){
sqlite3BtreeEnter(pBt);
nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt));
sqlite3BtreeLeave(pBt);
- if( db->xWalCallback && nEntry>0 && rc==SQLITE_OK ){
+ if( nEntry>0 && db->xWalCallback && rc==SQLITE_OK ){
rc = db->xWalCallback(db->pWalArg, db, db->aDb[i].zDbSName, nEntry);
}
}
@@ -75725,7 +78344,7 @@ static int sqlite3Step(Vdbe *p){
if( rc!=SQLITE_ROW ) checkProfileCallback(db, p);
#endif
- if( rc==SQLITE_DONE ){
+ if( rc==SQLITE_DONE && db->autoCommit ){
assert( p->rc==SQLITE_OK );
p->rc = doWalCallbacks(db);
if( p->rc!=SQLITE_OK ){
@@ -75749,8 +78368,11 @@ static int sqlite3Step(Vdbe *p){
|| (rc&0xff)==SQLITE_BUSY || rc==SQLITE_MISUSE
);
assert( (p->rc!=SQLITE_ROW && p->rc!=SQLITE_DONE) || p->rc==p->rcApp );
- if( p->isPrepareV2 && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
- /* If this statement was prepared using sqlite3_prepare_v2(), and an
+ if( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0
+ && rc!=SQLITE_ROW
+ && rc!=SQLITE_DONE
+ ){
+ /* If this statement was prepared using saved SQL and an
** error has occurred, then return the error code in p->rc to the
** caller. Set the error code in the database handle to the same value.
*/
@@ -75766,7 +78388,6 @@ static int sqlite3Step(Vdbe *p){
*/
SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){
int rc = SQLITE_OK; /* Result from sqlite3Step() */
- int rc2 = SQLITE_OK; /* Result from sqlite3Reprepare() */
Vdbe *v = (Vdbe*)pStmt; /* the prepared statement */
int cnt = 0; /* Counter to prevent infinite loop of reprepares */
sqlite3 *db; /* The database connection */
@@ -75780,32 +78401,31 @@ SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){
while( (rc = sqlite3Step(v))==SQLITE_SCHEMA
&& cnt++ < SQLITE_MAX_SCHEMA_RETRY ){
int savedPc = v->pc;
- rc2 = rc = sqlite3Reprepare(v);
- if( rc!=SQLITE_OK) break;
+ rc = sqlite3Reprepare(v);
+ if( rc!=SQLITE_OK ){
+ /* This case occurs after failing to recompile an sql statement.
+ ** The error message from the SQL compiler has already been loaded
+ ** into the database handle. This block copies the error message
+ ** from the database handle into the statement and sets the statement
+ ** program counter to 0 to ensure that when the statement is
+ ** finalized or reset the parser error message is available via
+ ** sqlite3_errmsg() and sqlite3_errcode().
+ */
+ const char *zErr = (const char *)sqlite3_value_text(db->pErr);
+ sqlite3DbFree(db, v->zErrMsg);
+ if( !db->mallocFailed ){
+ v->zErrMsg = sqlite3DbStrDup(db, zErr);
+ v->rc = rc = sqlite3ApiExit(db, rc);
+ } else {
+ v->zErrMsg = 0;
+ v->rc = rc = SQLITE_NOMEM_BKPT;
+ }
+ break;
+ }
sqlite3_reset(pStmt);
if( savedPc>=0 ) v->doingRerun = 1;
assert( v->expired==0 );
}
- if( rc2!=SQLITE_OK ){
- /* This case occurs after failing to recompile an sql statement.
- ** The error message from the SQL compiler has already been loaded
- ** into the database handle. This block copies the error message
- ** from the database handle into the statement and sets the statement
- ** program counter to 0 to ensure that when the statement is
- ** finalized or reset the parser error message is available via
- ** sqlite3_errmsg() and sqlite3_errcode().
- */
- const char *zErr = (const char *)sqlite3_value_text(db->pErr);
- sqlite3DbFree(db, v->zErrMsg);
- if( !db->mallocFailed ){
- v->zErrMsg = sqlite3DbStrDup(db, zErr);
- v->rc = rc2;
- } else {
- v->zErrMsg = 0;
- v->rc = rc = SQLITE_NOMEM_BKPT;
- }
- }
- rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
return rc;
}
@@ -75835,6 +78455,25 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context *p){
return p->pOut->db;
}
+/*
+** If this routine is invoked from within an xColumn method of a virtual
+** table, then it returns true if and only if the the call is during an
+** UPDATE operation and the value of the column will not be modified
+** by the UPDATE.
+**
+** If this routine is called from any context other than within the
+** xColumn method of a virtual table, then the return value is meaningless
+** and arbitrary.
+**
+** Virtual table implements might use this routine to optimize their
+** performance by substituting a NULL result, or some other light-weight
+** value, as a signal to the xUpdate routine that the column is unchanged.
+*/
+SQLITE_API int sqlite3_vtab_nochange(sqlite3_context *p){
+ assert( p );
+ return sqlite3_value_nochange(p->pOut);
+}
+
/*
** Return the current time for a statement. If the current time
** is requested more than once within the same run of a single prepared
@@ -75920,6 +78559,12 @@ SQLITE_API void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){
/*
** Return the auxiliary data pointer, if any, for the iArg'th argument to
** the user-function defined by pCtx.
+**
+** The left-most argument is 0.
+**
+** Undocumented behavior: If iArg is negative then access a cache of
+** auxiliary data pointers that is available to all functions within a
+** single prepared statement. The iArg values must match.
*/
SQLITE_API void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){
AuxData *pAuxData;
@@ -75930,17 +78575,24 @@ SQLITE_API void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){
#else
assert( pCtx->pVdbe!=0 );
#endif
- for(pAuxData=pCtx->pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNext){
- if( pAuxData->iOp==pCtx->iOp && pAuxData->iArg==iArg ) break;
+ for(pAuxData=pCtx->pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNextAux){
+ if( pAuxData->iAuxArg==iArg && (pAuxData->iAuxOp==pCtx->iOp || iArg<0) ){
+ return pAuxData->pAux;
+ }
}
-
- return (pAuxData ? pAuxData->pAux : 0);
+ return 0;
}
/*
** Set the auxiliary data pointer and delete function, for the iArg'th
** argument to the user-function defined by pCtx. Any previous value is
** deleted by calling the delete function specified when it was set.
+**
+** The left-most argument is 0.
+**
+** Undocumented behavior: If iArg is negative then make the data available
+** to all functions within the current prepared statement using iArg as an
+** access code.
*/
SQLITE_API void sqlite3_set_auxdata(
sqlite3_context *pCtx,
@@ -75952,33 +78604,34 @@ SQLITE_API void sqlite3_set_auxdata(
Vdbe *pVdbe = pCtx->pVdbe;
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
- if( iArg<0 ) goto failed;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
if( pVdbe==0 ) goto failed;
#else
assert( pVdbe!=0 );
#endif
- for(pAuxData=pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNext){
- if( pAuxData->iOp==pCtx->iOp && pAuxData->iArg==iArg ) break;
+ for(pAuxData=pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNextAux){
+ if( pAuxData->iAuxArg==iArg && (pAuxData->iAuxOp==pCtx->iOp || iArg<0) ){
+ break;
+ }
}
if( pAuxData==0 ){
pAuxData = sqlite3DbMallocZero(pVdbe->db, sizeof(AuxData));
if( !pAuxData ) goto failed;
- pAuxData->iOp = pCtx->iOp;
- pAuxData->iArg = iArg;
- pAuxData->pNext = pVdbe->pAuxData;
+ pAuxData->iAuxOp = pCtx->iOp;
+ pAuxData->iAuxArg = iArg;
+ pAuxData->pNextAux = pVdbe->pAuxData;
pVdbe->pAuxData = pAuxData;
if( pCtx->fErrorOrAux==0 ){
pCtx->isError = 0;
pCtx->fErrorOrAux = 1;
}
- }else if( pAuxData->xDelete ){
- pAuxData->xDelete(pAuxData->pAux);
+ }else if( pAuxData->xDeleteAux ){
+ pAuxData->xDeleteAux(pAuxData->pAux);
}
pAuxData->pAux = pAux;
- pAuxData->xDelete = xDelete;
+ pAuxData->xDeleteAux = xDelete;
return;
failed:
@@ -76375,9 +79028,8 @@ static int vdbeUnbind(Vdbe *p, int i){
** as if there had been a schema change, on the first sqlite3_step() call
** following any change to the bindings of that parameter.
*/
- if( p->isPrepareV2 &&
- ((i<32 && p->expmask & ((u32)1 << i)) || p->expmask==0xffffffff)
- ){
+ assert( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 || p->expmask==0 );
+ if( p->expmask!=0 && (p->expmask & (i>=31 ? 0x80000000 : (u32)1<expired = 1;
}
return SQLITE_OK;
@@ -76406,8 +79058,10 @@ static int bindText(
if( rc==SQLITE_OK && encoding!=0 ){
rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db));
}
- sqlite3Error(p->db, rc);
- rc = sqlite3ApiExit(p->db, rc);
+ if( rc ){
+ sqlite3Error(p->db, rc);
+ rc = sqlite3ApiExit(p->db, rc);
+ }
}
sqlite3_mutex_leave(p->db->mutex);
}else if( xDel!=SQLITE_STATIC && xDel!=SQLITE_TRANSIENT ){
@@ -76478,6 +79132,24 @@ SQLITE_API int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){
}
return rc;
}
+SQLITE_API int sqlite3_bind_pointer(
+ sqlite3_stmt *pStmt,
+ int i,
+ void *pPtr,
+ const char *zPTtype,
+ void (*xDestructor)(void*)
+){
+ int rc;
+ Vdbe *p = (Vdbe*)pStmt;
+ rc = vdbeUnbind(p, i);
+ if( rc==SQLITE_OK ){
+ sqlite3VdbeMemSetPointer(&p->aVar[i-1], pPtr, zPTtype, xDestructor);
+ sqlite3_mutex_leave(p->db->mutex);
+ }else if( xDestructor ){
+ xDestructor(pPtr);
+ }
+ return rc;
+}
SQLITE_API int sqlite3_bind_text(
sqlite3_stmt *pStmt,
int i,
@@ -76587,10 +79259,8 @@ SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){
*/
SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt *pStmt, int i){
Vdbe *p = (Vdbe*)pStmt;
- if( p==0 || i<1 || i>p->nzVar ){
- return 0;
- }
- return p->azVar[i-1];
+ if( p==0 ) return 0;
+ return sqlite3VListNumToName(p->pVList, i);
}
/*
@@ -76599,19 +79269,8 @@ SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt *pStmt, int i){
** return 0.
*/
SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe *p, const char *zName, int nName){
- int i;
- if( p==0 ){
- return 0;
- }
- if( zName ){
- for(i=0; inzVar; i++){
- const char *z = p->azVar[i];
- if( z && strncmp(z,zName,nName)==0 && z[nName]==0 ){
- return i+1;
- }
- }
- }
- return 0;
+ if( p==0 || zName==0 ) return 0;
+ return sqlite3VListNameToNum(p->pVList, zName, nName);
}
SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){
return sqlite3VdbeParameterIndex((Vdbe*)pStmt, zName, sqlite3Strlen30(zName));
@@ -76653,10 +79312,12 @@ SQLITE_API int sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *
if( pFrom->nVar!=pTo->nVar ){
return SQLITE_ERROR;
}
- if( pTo->isPrepareV2 && pTo->expmask ){
+ assert( (pTo->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 || pTo->expmask==0 );
+ if( pTo->expmask ){
pTo->expired = 1;
}
- if( pFrom->isPrepareV2 && pFrom->expmask ){
+ assert( (pFrom->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 || pFrom->expmask==0 );
+ if( pFrom->expmask ){
pFrom->expired = 1;
}
return sqlite3TransferBindings(pFromStmt, pToStmt);
@@ -76725,8 +79386,19 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){
return 0;
}
#endif
- v = pVdbe->aCounter[op];
- if( resetFlag ) pVdbe->aCounter[op] = 0;
+ if( op==SQLITE_STMTSTATUS_MEMUSED ){
+ sqlite3 *db = pVdbe->db;
+ sqlite3_mutex_enter(db->mutex);
+ v = 0;
+ db->pnBytesFreed = (int*)&v;
+ sqlite3VdbeClearObject(db, pVdbe);
+ sqlite3DbFree(db, pVdbe);
+ db->pnBytesFreed = 0;
+ sqlite3_mutex_leave(db->mutex);
+ }else{
+ v = pVdbe->aCounter[op];
+ if( resetFlag ) pVdbe->aCounter[op] = 0;
+ }
return (int)v;
}
@@ -76774,12 +79446,11 @@ static UnpackedRecord *vdbeUnpackRecord(
int nKey,
const void *pKey
){
- char *dummy; /* Dummy argument for AllocUnpackedRecord() */
UnpackedRecord *pRet; /* Return value */
- pRet = sqlite3VdbeAllocUnpackedRecord(pKeyInfo, 0, 0, &dummy);
+ pRet = sqlite3VdbeAllocUnpackedRecord(pKeyInfo);
if( pRet ){
- memset(pRet->aMem, 0, sizeof(Mem)*(pKeyInfo->nField+1));
+ memset(pRet->aMem, 0, sizeof(Mem)*(pKeyInfo->nKeyField+1));
sqlite3VdbeRecordUnpack(pKeyInfo, nKey, pKey, pRet);
}
return pRet;
@@ -76791,6 +79462,7 @@ static UnpackedRecord *vdbeUnpackRecord(
*/
SQLITE_API int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
PreUpdate *p = db->pPreUpdate;
+ Mem *pMem;
int rc = SQLITE_OK;
/* Test that this call is being made from within an SQLITE_DELETE or
@@ -76799,6 +79471,9 @@ SQLITE_API int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppVa
rc = SQLITE_MISUSE_BKPT;
goto preupdate_old_out;
}
+ if( p->pPk ){
+ iIdx = sqlite3ColumnOfIndex(p->pPk, iIdx);
+ }
if( iIdx>=p->pCsr->nField || iIdx<0 ){
rc = SQLITE_RANGE;
goto preupdate_old_out;
@@ -76812,7 +79487,7 @@ SQLITE_API int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppVa
nRec = sqlite3BtreePayloadSize(p->pCsr->uc.pCursor);
aRec = sqlite3DbMallocRaw(db, nRec);
if( !aRec ) goto preupdate_old_out;
- rc = sqlite3BtreeData(p->pCsr->uc.pCursor, 0, nRec, aRec);
+ rc = sqlite3BtreePayload(p->pCsr->uc.pCursor, 0, nRec, aRec);
if( rc==SQLITE_OK ){
p->pUnpacked = vdbeUnpackRecord(&p->keyinfo, nRec, aRec);
if( !p->pUnpacked ) rc = SQLITE_NOMEM;
@@ -76824,17 +79499,14 @@ SQLITE_API int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppVa
p->aRecord = aRec;
}
- if( iIdx>=p->pUnpacked->nField ){
+ pMem = *ppValue = &p->pUnpacked->aMem[iIdx];
+ if( iIdx==p->pTab->iPKey ){
+ sqlite3VdbeMemSetInt64(pMem, p->iKey1);
+ }else if( iIdx>=p->pUnpacked->nField ){
*ppValue = (sqlite3_value *)columnNullValue();
- }else{
- Mem *pMem = *ppValue = &p->pUnpacked->aMem[iIdx];
- *ppValue = &p->pUnpacked->aMem[iIdx];
- if( iIdx==p->pTab->iPKey ){
- sqlite3VdbeMemSetInt64(pMem, p->iKey1);
- }else if( p->pTab->aCol[iIdx].affinity==SQLITE_AFF_REAL ){
- if( pMem->flags & MEM_Int ){
- sqlite3VdbeMemRealify(pMem);
- }
+ }else if( p->pTab->aCol[iIdx].affinity==SQLITE_AFF_REAL ){
+ if( pMem->flags & MEM_Int ){
+ sqlite3VdbeMemRealify(pMem);
}
}
@@ -76851,7 +79523,7 @@ SQLITE_API int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppVa
*/
SQLITE_API int sqlite3_preupdate_count(sqlite3 *db){
PreUpdate *p = db->pPreUpdate;
- return (p ? p->keyinfo.nField : 0);
+ return (p ? p->keyinfo.nKeyField : 0);
}
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
@@ -76887,6 +79559,9 @@ SQLITE_API int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppVa
rc = SQLITE_MISUSE_BKPT;
goto preupdate_new_out;
}
+ if( p->pPk && p->op!=SQLITE_UPDATE ){
+ iIdx = sqlite3ColumnOfIndex(p->pPk, iIdx);
+ }
if( iIdx>=p->pCsr->nField || iIdx<0 ){
rc = SQLITE_RANGE;
goto preupdate_new_out;
@@ -76907,13 +79582,11 @@ SQLITE_API int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppVa
}
p->pNewUnpacked = pUnpack;
}
- if( iIdx>=pUnpack->nField ){
+ pMem = &pUnpack->aMem[iIdx];
+ if( iIdx==p->pTab->iPKey ){
+ sqlite3VdbeMemSetInt64(pMem, p->iKey2);
+ }else if( iIdx>=pUnpack->nField ){
pMem = (sqlite3_value *)columnNullValue();
- }else{
- pMem = &pUnpack->aMem[iIdx];
- if( iIdx==p->pTab->iPKey ){
- sqlite3VdbeMemSetInt64(pMem, p->iKey2);
- }
}
}else{
/* For an UPDATE, memory cell (p->iNewReg+1+iIdx) contains the required
@@ -77103,7 +79776,7 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql(
Mem *pVar; /* Value of a host parameter */
StrAccum out; /* Accumulate the output here */
#ifndef SQLITE_OMIT_UTF16
- Mem utf8; /* Used to convert UTF16 parameters into UTF8 for display */
+ Mem utf8; /* Used to convert UTF16 into UTF8 for display */
#endif
char zBase[100]; /* Initial working space */
@@ -77329,7 +80002,7 @@ SQLITE_API int sqlite3_found_count = 0;
** Test a register to see if it exceeds the current maximum blob size.
** If it does, record the new maximum blob size.
*/
-#if defined(SQLITE_TEST) && !defined(SQLITE_OMIT_BUILTIN_TEST)
+#if defined(SQLITE_TEST) && !defined(SQLITE_UNTESTABLE)
# define UPDATE_MAX_BLOBSIZE(P) updateMaxBlobsize(P)
#else
# define UPDATE_MAX_BLOBSIZE(P)
@@ -77439,7 +80112,7 @@ static VdbeCursor *allocateCursor(
}
if( SQLITE_OK==sqlite3VdbeMemClearAndResize(pMem, nByte) ){
p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->z;
- memset(pCx, 0, sizeof(VdbeCursor));
+ memset(pCx, 0, offsetof(VdbeCursor,pAltCursor));
pCx->eCurType = eCurType;
pCx->iDb = iDb;
pCx->nField = nField;
@@ -77572,7 +80245,7 @@ static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){
if( sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc)==0 ){
return 0;
}
- if( sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc)==SQLITE_OK ){
+ if( sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc)==0 ){
return MEM_Int;
}
return MEM_Real;
@@ -77621,9 +80294,7 @@ SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){
}else{
c = 's';
}
-
- sqlite3_snprintf(100, zCsr, "%c", c);
- zCsr += sqlite3Strlen30(zCsr);
+ *(zCsr++) = c;
sqlite3_snprintf(100, zCsr, "%d[", pMem->n);
zCsr += sqlite3Strlen30(zCsr);
for(i=0; i<16 && in; i++){
@@ -77635,9 +80306,7 @@ SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){
if( z<32 || z>126 ) *zCsr++ = '.';
else *zCsr++ = z;
}
-
- sqlite3_snprintf(100, zCsr, "]%s", encnames[pMem->enc]);
- zCsr += sqlite3Strlen30(zCsr);
+ *(zCsr++) = ']';
if( f & MEM_Zero ){
sqlite3_snprintf(100, zCsr,"+%dz",pMem->u.nZero);
zCsr += sqlite3Strlen30(zCsr);
@@ -77686,7 +80355,7 @@ static void memTracePrint(Mem *p){
if( p->flags & MEM_Undefined ){
printf(" undefined");
}else if( p->flags & MEM_Null ){
- printf(" NULL");
+ printf(p->flags & MEM_Zero ? " NULL-nochng" : " NULL");
}else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){
printf(" si:%lld", p->u.i);
}else if( p->flags & MEM_Int ){
@@ -77708,6 +80377,7 @@ static void registerTrace(int iReg, Mem *p){
printf("REG[%d] = ", iReg);
memTracePrint(p);
printf("\n");
+ sqlite3VdbeCheckMemInvariants(p);
}
#endif
@@ -77883,15 +80553,13 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
int iCompare = 0; /* Result of last comparison */
unsigned nVmStep = 0; /* Number of virtual machine steps */
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
- unsigned nProgressLimit = 0;/* Invoke xProgress() when nVmStep reaches this */
+ unsigned nProgressLimit; /* Invoke xProgress() when nVmStep reaches this */
#endif
Mem *aMem = p->aMem; /* Copy of p->aMem */
Mem *pIn1 = 0; /* 1st input operand */
Mem *pIn2 = 0; /* 2nd input operand */
Mem *pIn3 = 0; /* 3rd input operand */
Mem *pOut = 0; /* Output operand */
- int *aPermute = 0; /* Permutation of columns for OP_Compare */
- i64 lastRowid = db->lastRowid; /* Saved value of the last insert ROWID */
#ifdef VDBE_PROFILE
u64 start; /* CPU clock count at start of opcode */
#endif
@@ -77906,7 +80574,6 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
}
assert( p->rc==SQLITE_OK || (p->rc&0xff)==SQLITE_BUSY );
assert( p->bIsReader || p->readOnly!=0 );
- p->rc = SQLITE_OK;
p->iCurrentTime = 0;
assert( p->explain==0 );
p->pResultSet = 0;
@@ -77918,6 +80585,8 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
u32 iPrior = p->aCounter[SQLITE_STMTSTATUS_VM_STEP];
assert( 0 < db->nProgressOps );
nProgressLimit = db->nProgressOps - (iPrior % db->nProgressOps);
+ }else{
+ nProgressLimit = 0xffffffff;
}
#endif
#ifdef SQLITE_DEBUG
@@ -78077,7 +80746,7 @@ case OP_Goto: { /* jump */
pOp = &aOp[pOp->p2 - 1];
/* Opcodes that are used as the bottom of a loop (OP_Next, OP_Prev,
- ** OP_VNext, OP_RowSetNext, or OP_SorterNext) all jump here upon
+ ** OP_VNext, or OP_SorterNext) all jump here upon
** completion. Check to see if sqlite3_interrupt() has been called
** or if the progress callback needs to be invoked.
**
@@ -78095,7 +80764,7 @@ case OP_Goto: { /* jump */
** If the progress callback returns non-zero, exit the virtual machine with
** a return code SQLITE_ABORT.
*/
- if( db->xProgress!=0 && nVmStep>=nProgressLimit ){
+ if( nVmStep>=nProgressLimit && db->xProgress!=0 ){
assert( db->nProgressOps!=0 );
nProgressLimit = nVmStep + db->nProgressOps - (nVmStep%db->nProgressOps);
if( db->xProgress(db->pProgressArg) ){
@@ -78267,7 +80936,6 @@ case OP_Halt: {
p->nFrame--;
sqlite3VdbeSetChanges(db, p->nChange);
pcx = sqlite3VdbeFrameRestore(pFrame);
- lastRowid = db->lastRowid;
if( pOp->p2==OE_Ignore ){
/* Instruction pcx is the OP_Program that invoked the sub-program
** currently being halted. If the p2 instruction of this OP_Halt
@@ -78284,7 +80952,7 @@ case OP_Halt: {
p->rc = pOp->p1;
p->errorAction = (u8)pOp->p2;
p->pc = pcx;
- assert( pOp->p5>=0 && pOp->p5<=4 );
+ assert( pOp->p5<=4 );
if( p->rc ){
if( pOp->p5 ){
static const char * const azType[] = { "NOT NULL", "UNIQUE", "CHECK",
@@ -78466,7 +81134,7 @@ case OP_Null: { /* out2 */
case OP_SoftNull: {
assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) );
pOut = &aMem[pOp->p1];
- pOut->flags = (pOut->flags|MEM_Null)&~MEM_Undefined;
+ pOut->flags = (pOut->flags&~(MEM_Undefined|MEM_AffMask))|MEM_Null;
break;
}
@@ -78497,12 +81165,12 @@ case OP_Variable: { /* out2 */
Mem *pVar; /* Value being transferred */
assert( pOp->p1>0 && pOp->p1<=p->nVar );
- assert( pOp->p4.z==0 || pOp->p4.z==p->azVar[pOp->p1-1] );
+ assert( pOp->p4.z==0 || pOp->p4.z==sqlite3VListNumToName(p->pVList,pOp->p1) );
pVar = &p->aVar[pOp->p1 - 1];
if( sqlite3VdbeMemTooBig(pVar) ){
goto too_big;
}
- pOut = out2Prerelease(p, pOp);
+ pOut = &aMem[pOp->p2];
sqlite3VdbeMemShallowCopy(pOut, pVar, MEM_Static);
UPDATE_MAX_BLOBSIZE(pOut);
break;
@@ -78638,7 +81306,7 @@ case OP_ResultRow: {
/* Run the progress counter just before returning.
*/
if( db->xProgress!=0
- && nVmStep>=nProgressLimit
+ && nVmStep>=nProgressLimit
&& db->xProgress(db->pProgressArg)!=0
){
rc = SQLITE_INTERRUPT;
@@ -78809,7 +81477,6 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
type2 = numericType(pIn2);
pOut = &aMem[pOp->p3];
flags = pIn1->flags | pIn2->flags;
- if( (flags & MEM_Null)!=0 ) goto arithmetic_result_is_null;
if( (type1 & type2 & MEM_Int)!=0 ){
iA = pIn1->u.i;
iB = pIn2->u.i;
@@ -78833,6 +81500,8 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
}
pOut->u.i = iB;
MemSetTypeFlag(pOut, MEM_Int);
+ }else if( (flags & MEM_Null)!=0 ){
+ goto arithmetic_result_is_null;
}else{
bIntint = 0;
fp_math:
@@ -78880,7 +81549,7 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
/* Opcode: CollSeq P1 * * P4
**
-** P4 is a pointer to a CollSeq struct. If the next call to a user function
+** P4 is a pointer to a CollSeq object. If the next call to a user function
** or aggregate calls sqlite3GetFuncCollSeq(), this collation sequence will
** be returned. This is used by the built-in min(), max() and nullif()
** functions.
@@ -78901,119 +81570,6 @@ case OP_CollSeq: {
break;
}
-/* Opcode: Function0 P1 P2 P3 P4 P5
-** Synopsis: r[P3]=func(r[P2@P5])
-**
-** Invoke a user function (P4 is a pointer to a FuncDef object 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
-** whether meta data associated with a user function argument using the
-** sqlite3_set_auxdata() API may be safely retained until the next
-** invocation of this opcode.
-**
-** See also: Function, AggStep, AggFinal
-*/
-/* Opcode: Function P1 P2 P3 P4 P5
-** Synopsis: r[P3]=func(r[P2@P5])
-**
-** Invoke a user function (P4 is a pointer to an sqlite3_context object that
-** contains a pointer to the function to be run) 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
-** whether meta data associated with a user function argument using the
-** sqlite3_set_auxdata() API may be safely retained until the next
-** invocation of this opcode.
-**
-** SQL functions are initially coded as OP_Function0 with P4 pointing
-** to a FuncDef object. But on first evaluation, the P4 operand is
-** automatically converted into an sqlite3_context object and the operation
-** changed to this OP_Function opcode. In this way, the initialization of
-** the sqlite3_context object occurs only once, rather than once for each
-** evaluation of the function.
-**
-** See also: Function0, AggStep, AggFinal
-*/
-case OP_Function0: {
- int n;
- sqlite3_context *pCtx;
-
- assert( pOp->p4type==P4_FUNCDEF );
- n = pOp->p5;
- assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
- assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem+1 - p->nCursor)+1) );
- assert( pOp->p3p2 || pOp->p3>=pOp->p2+n );
- pCtx = sqlite3DbMallocRawNN(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*));
- if( pCtx==0 ) goto no_mem;
- pCtx->pOut = 0;
- pCtx->pFunc = pOp->p4.pFunc;
- pCtx->iOp = (int)(pOp - aOp);
- pCtx->pVdbe = p;
- pCtx->argc = n;
- pOp->p4type = P4_FUNCCTX;
- pOp->p4.pCtx = pCtx;
- pOp->opcode = OP_Function;
- /* Fall through into OP_Function */
-}
-case OP_Function: {
- int i;
- sqlite3_context *pCtx;
-
- assert( pOp->p4type==P4_FUNCCTX );
- pCtx = pOp->p4.pCtx;
-
- /* If this function is inside of a trigger, the register array in aMem[]
- ** might change from one evaluation to the next. The next block of code
- ** checks to see if the register array has changed, and if so it
- ** reinitializes the relavant parts of the sqlite3_context object */
- pOut = &aMem[pOp->p3];
- if( pCtx->pOut != pOut ){
- pCtx->pOut = pOut;
- for(i=pCtx->argc-1; i>=0; i--) pCtx->argv[i] = &aMem[pOp->p2+i];
- }
-
- memAboutToChange(p, pCtx->pOut);
-#ifdef SQLITE_DEBUG
- for(i=0; iargc; i++){
- assert( memIsValid(pCtx->argv[i]) );
- REGISTER_TRACE(pOp->p2+i, pCtx->argv[i]);
- }
-#endif
- MemSetTypeFlag(pCtx->pOut, MEM_Null);
- pCtx->fErrorOrAux = 0;
- db->lastRowid = lastRowid;
- (*pCtx->pFunc->xSFunc)(pCtx, pCtx->argc, pCtx->argv);/* IMP: R-24505-23230 */
- lastRowid = db->lastRowid; /* Remember rowid changes made by xSFunc */
-
- /* If the function returned an error, throw an exception */
- if( pCtx->fErrorOrAux ){
- if( pCtx->isError ){
- sqlite3VdbeError(p, "%s", sqlite3_value_text(pCtx->pOut));
- rc = pCtx->isError;
- }
- sqlite3VdbeDeleteAuxData(db, &p->pAuxData, pCtx->iOp, pOp->p1);
- if( rc ) goto abort_due_to_error;
- }
-
- /* Copy the result of the function into register P3 */
- if( pOut->flags & (MEM_Str|MEM_Blob) ){
- sqlite3VdbeChangeEncoding(pCtx->pOut, encoding);
- if( sqlite3VdbeMemTooBig(pCtx->pOut) ) goto too_big;
- }
-
- REGISTER_TRACE(pOp->p3, pCtx->pOut);
- UPDATE_MAX_BLOBSIZE(pCtx->pOut);
- break;
-}
-
/* Opcode: BitAnd P1 P2 P3 * *
** Synopsis: r[P3]=r[P1]&r[P2]
**
@@ -79163,11 +81719,11 @@ case OP_RealAffinity: { /* in1 */
** Force the value in register P1 to be the type defined by P2.
**
**
-** - TEXT
-**
- BLOB
-**
- NUMERIC
-**
- INTEGER
-**
- REAL
+**
- P2=='A' → BLOB
+**
- P2=='B' → TEXT
+**
- P2=='C' → NUMERIC
+**
- P2=='D' → INTEGER
+**
- P2=='E' → REAL
**
**
** A NULL value is not changed by this routine. It remains NULL.
@@ -79310,8 +81866,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne );
assert( (flags1 & MEM_Cleared)==0 );
assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 );
- if( (flags1&MEM_Null)!=0
- && (flags3&MEM_Null)!=0
+ if( (flags1&flags3&MEM_Null)!=0
&& (flags3&MEM_Cleared)==0
){
res = 0; /* Operands are equal */
@@ -79380,13 +81935,23 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl);
}
compare_op:
- switch( pOp->opcode ){
- case OP_Eq: res2 = res==0; break;
- case OP_Ne: res2 = res; break;
- case OP_Lt: res2 = res<0; break;
- case OP_Le: res2 = res<=0; break;
- case OP_Gt: res2 = res>0; break;
- default: res2 = res>=0; break;
+ /* At this point, res is negative, zero, or positive if reg[P1] is
+ ** less than, equal to, or greater than reg[P3], respectively. Compute
+ ** the answer to this operator in res2, depending on what the comparison
+ ** operator actually is. The next block of code depends on the fact
+ ** that the 6 comparison operators are consecutive integers in this
+ ** order: NE, EQ, GT, LE, LT, GE */
+ assert( OP_Eq==OP_Ne+1 ); assert( OP_Gt==OP_Ne+2 ); assert( OP_Le==OP_Ne+3 );
+ assert( OP_Lt==OP_Ne+4 ); assert( OP_Ge==OP_Ne+5 );
+ if( res<0 ){ /* ne, eq, gt, le, lt, ge */
+ static const unsigned char aLTb[] = { 1, 0, 0, 1, 1, 0 };
+ res2 = aLTb[pOp->opcode - OP_Ne];
+ }else if( res==0 ){
+ static const unsigned char aEQb[] = { 0, 1, 0, 1, 0, 1 };
+ res2 = aEQb[pOp->opcode - OP_Ne];
+ }else{
+ static const unsigned char aGTb[] = { 1, 0, 1, 0, 0, 1 };
+ res2 = aGTb[pOp->opcode - OP_Ne];
}
/* Undo any changes made by applyAffinity() to the input registers. */
@@ -79398,7 +81963,6 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
if( pOp->p5 & SQLITE_STOREP2 ){
pOut = &aMem[pOp->p2];
iCompare = res;
- res2 = res2!=0; /* For this path res2 must be exactly 0 or 1 */
if( (pOp->p5 & SQLITE_KEEPNULL)!=0 ){
/* The KEEPNULL flag prevents OP_Eq from overwriting a NULL with 1
** and prevents OP_Ne from overwriting NULL with 0. This flag
@@ -79448,8 +82012,8 @@ case OP_ElseNotEq: { /* same as TK_ESCAPE, jump */
/* Opcode: Permutation * * * P4 *
**
-** Set the permutation used by the OP_Compare operator to be the array
-** of integers in P4.
+** Set the permutation used by the OP_Compare operator in the next
+** instruction. The permutation is stored in the P4 operand.
**
** The permutation is only valid until the next OP_Compare that has
** the OPFLAG_PERMUTE bit set in P5. Typically the OP_Permutation should
@@ -79461,7 +82025,8 @@ case OP_ElseNotEq: { /* same as TK_ESCAPE, jump */
case OP_Permutation: {
assert( pOp->p4type==P4_INTARRAY );
assert( pOp->p4.ai );
- aPermute = pOp->p4.ai + 1;
+ assert( pOp[1].opcode==OP_Compare );
+ assert( pOp[1].p5 & OPFLAG_PERMUTE );
break;
}
@@ -79494,15 +82059,24 @@ case OP_Compare: {
int idx;
CollSeq *pColl; /* Collating sequence to use on this term */
int bRev; /* True for DESCENDING sort order */
+ int *aPermute; /* The permutation */
- if( (pOp->p5 & OPFLAG_PERMUTE)==0 ) aPermute = 0;
+ if( (pOp->p5 & OPFLAG_PERMUTE)==0 ){
+ aPermute = 0;
+ }else{
+ assert( pOp>aOp );
+ assert( pOp[-1].opcode==OP_Permutation );
+ assert( pOp[-1].p4type==P4_INTARRAY );
+ aPermute = pOp[-1].p4.ai + 1;
+ assert( aPermute!=0 );
+ }
n = pOp->p3;
pKeyInfo = pOp->p4.pKeyInfo;
assert( n>0 );
assert( pKeyInfo!=0 );
p1 = pOp->p1;
p2 = pOp->p2;
-#if SQLITE_DEBUG
+#ifdef SQLITE_DEBUG
if( aPermute ){
int k, mx = 0;
for(k=0; kmx ) mx = aPermute[k];
@@ -79519,7 +82093,7 @@ case OP_Compare: {
assert( memIsValid(&aMem[p2+idx]) );
REGISTER_TRACE(p1+idx, &aMem[p1+idx]);
REGISTER_TRACE(p2+idx, &aMem[p2+idx]);
- assert( inField );
+ assert( inKeyField );
pColl = pKeyInfo->aColl[i];
bRev = pKeyInfo->aSortOrder[i];
iCompare = sqlite3MemCompare(&aMem[p1+idx], &aMem[p2+idx], pColl);
@@ -79528,7 +82102,6 @@ case OP_Compare: {
break;
}
}
- aPermute = 0;
break;
}
@@ -79641,19 +82214,39 @@ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */
/* Opcode: Once P1 P2 * * *
**
-** If the P1 value is equal to the P1 value on the OP_Init opcode at
-** instruction 0, then jump to P2. If the two P1 values differ, then
-** set the P1 value on this opcode to equal the P1 value on the OP_Init
-** and fall through.
+** Fall through to the next instruction the first time this opcode is
+** encountered on each invocation of the byte-code program. Jump to P2
+** on the second and all subsequent encounters during the same invocation.
+**
+** Top-level programs determine first invocation by comparing the P1
+** operand against the P1 operand on the OP_Init opcode at the beginning
+** of the program. If the P1 values differ, then fall through and make
+** the P1 of this opcode equal to the P1 of OP_Init. If P1 values are
+** the same then take the jump.
+**
+** For subprograms, there is a bitmask in the VdbeFrame that determines
+** whether or not the jump should be taken. The bitmask is necessary
+** because the self-altering code trick does not work for recursive
+** triggers.
*/
case OP_Once: { /* jump */
+ u32 iAddr; /* Address of this instruction */
assert( p->aOp[0].opcode==OP_Init );
- VdbeBranchTaken(p->aOp[0].p1==pOp->p1, 2);
- if( p->aOp[0].p1==pOp->p1 ){
- goto jump_to_p2;
+ if( p->pFrame ){
+ iAddr = (int)(pOp - p->aOp);
+ if( (p->pFrame->aOnce[iAddr/8] & (1<<(iAddr & 7)))!=0 ){
+ VdbeBranchTaken(1, 2);
+ goto jump_to_p2;
+ }
+ p->pFrame->aOnce[iAddr/8] |= 1<<(iAddr & 7);
}else{
- pOp->p1 = p->aOp[0].p1;
+ if( p->aOp[0].p1==pOp->p1 ){
+ VdbeBranchTaken(1, 2);
+ goto jump_to_p2;
+ }
}
+ VdbeBranchTaken(0, 2);
+ pOp->p1 = p->aOp[0].p1;
break;
}
@@ -79718,6 +82311,54 @@ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */
break;
}
+/* Opcode: IfNullRow P1 P2 P3 * *
+** Synopsis: if P1.nullRow then r[P3]=NULL, goto P2
+**
+** Check the cursor P1 to see if it is currently pointing at a NULL row.
+** If it is, then set register P3 to NULL and jump immediately to P2.
+** If P1 is not on a NULL row, then fall through without making any
+** changes.
+*/
+case OP_IfNullRow: { /* jump */
+ assert( pOp->p1>=0 && pOp->p1nCursor );
+ assert( p->apCsr[pOp->p1]!=0 );
+ if( p->apCsr[pOp->p1]->nullRow ){
+ sqlite3VdbeMemSetNull(aMem + pOp->p3);
+ goto jump_to_p2;
+ }
+ break;
+}
+
+#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
+/* Opcode: Offset P1 P2 P3 * *
+** Synopsis: r[P3] = sqlite_offset(P1)
+**
+** Store in register r[P3] the byte offset into the database file that is the
+** start of the payload for the record at which that cursor P1 is currently
+** pointing.
+**
+** P2 is the column number for the argument to the sqlite_offset() function.
+** This opcode does not use P2 itself, but the P2 value is used by the
+** code generator. The P1, P2, and P3 operands to this opcode are the
+** as as for OP_Column.
+**
+** This opcode is only available if SQLite is compiled with the
+** -DSQLITE_ENABLE_OFFSET_SQL_FUNC option.
+*/
+case OP_Offset: { /* out3 */
+ VdbeCursor *pC; /* The VDBE cursor */
+ assert( pOp->p1>=0 && pOp->p1nCursor );
+ pC = p->apCsr[pOp->p1];
+ pOut = &p->aMem[pOp->p3];
+ if( NEVER(pC==0) || pC->eCurType!=CURTYPE_BTREE ){
+ sqlite3VdbeMemSetNull(pOut);
+ }else{
+ sqlite3VdbeMemSetInt64(pOut, sqlite3BtreeOffset(pC->uc.pCursor));
+ }
+ break;
+}
+#endif /* SQLITE_ENABLE_OFFSET_SQL_FUNC */
+
/* Opcode: Column P1 P2 P3 P4 P5
** Synopsis: r[P3]=PX
**
@@ -79729,7 +82370,7 @@ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */
**
** The value extracted is stored in register P3.
**
-** If the column contains fewer than P2 fields, then extract a NULL. Or,
+** If the record contains fewer than P2 fields, then extract a NULL. Or,
** if the P4 argument is a P4_MEM use the value of the P4 argument as
** the result.
**
@@ -79738,7 +82379,7 @@ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */
** The first OP_Column against a pseudo-table after the value of the content
** register has changed should have this bit set.
**
-** If the OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG bits are set on P5 when
+** If the OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG bits are set on P5 then
** the result is guaranteed to only be used as the argument of a length()
** or typeof() function, respectively. The loading of large blobs can be
** skipped for length() and all content loading can be skipped for typeof().
@@ -79755,16 +82396,16 @@ case OP_Column: {
const u8 *zData; /* Part of the record being decoded */
const u8 *zHdr; /* Next unparsed byte of the header */
const u8 *zEndHdr; /* Pointer to first byte after the header */
- u32 offset; /* Offset into the data */
u64 offset64; /* 64-bit offset */
- u32 avail; /* Number of bytes of available data */
u32 t; /* A type code from the record header */
Mem *pReg; /* PseudoTable input register */
pC = p->apCsr[pOp->p1];
p2 = pOp->p2;
- /* If the cursor cache is stale, bring it up-to-date */
+ /* If the cursor cache is stale (meaning it is not currently point at
+ ** the correct row) then bring it up-to-date by doing the necessary
+ ** B-Tree seek. */
rc = sqlite3VdbeCursorMoveto(&pC, &p2);
if( rc ) goto abort_due_to_error;
@@ -79778,43 +82419,41 @@ case OP_Column: {
assert( pC->eCurType!=CURTYPE_VTAB );
assert( pC->eCurType!=CURTYPE_PSEUDO || pC->nullRow );
assert( pC->eCurType!=CURTYPE_SORTER );
- pCrsr = pC->uc.pCursor;
if( pC->cacheStatus!=p->cacheCtr ){ /*OPTIMIZATION-IF-FALSE*/
if( pC->nullRow ){
if( pC->eCurType==CURTYPE_PSEUDO ){
- assert( pC->uc.pseudoTableReg>0 );
- pReg = &aMem[pC->uc.pseudoTableReg];
+ /* For the special case of as pseudo-cursor, the seekResult field
+ ** identifies the register that holds the record */
+ assert( pC->seekResult>0 );
+ pReg = &aMem[pC->seekResult];
assert( pReg->flags & MEM_Blob );
assert( memIsValid(pReg) );
- pC->payloadSize = pC->szRow = avail = pReg->n;
+ pC->payloadSize = pC->szRow = pReg->n;
pC->aRow = (u8*)pReg->z;
}else{
sqlite3VdbeMemSetNull(pDest);
goto op_column_out;
}
}else{
+ pCrsr = pC->uc.pCursor;
assert( pC->eCurType==CURTYPE_BTREE );
assert( pCrsr );
assert( sqlite3BtreeCursorIsValid(pCrsr) );
pC->payloadSize = sqlite3BtreePayloadSize(pCrsr);
- pC->aRow = sqlite3BtreePayloadFetch(pCrsr, &avail);
- assert( avail<=65536 ); /* Maximum page size is 64KiB */
- if( pC->payloadSize <= (u32)avail ){
- pC->szRow = pC->payloadSize;
- }else if( pC->payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
+ pC->aRow = sqlite3BtreePayloadFetch(pCrsr, &pC->szRow);
+ assert( pC->szRow<=pC->payloadSize );
+ assert( pC->szRow<=65536 ); /* Maximum page size is 64KiB */
+ if( pC->payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
- }else{
- pC->szRow = avail;
}
}
pC->cacheStatus = p->cacheCtr;
- pC->iHdrOffset = getVarint32(pC->aRow, offset);
+ pC->iHdrOffset = getVarint32(pC->aRow, aOffset[0]);
pC->nHdrParsed = 0;
- aOffset[0] = offset;
- if( availszRowaRow does not have to hold the entire row, but it does at least
** need to cover the header of the record. If pC->aRow does not contain
** the complete header, then set it to zero, forcing the header to be
@@ -79831,17 +82470,26 @@ case OP_Column: {
** 3-byte type for each of the maximum of 32768 columns plus three
** extra bytes for the header length itself. 32768*3 + 3 = 98307.
*/
- if( offset > 98307 || offset > pC->payloadSize ){
- rc = SQLITE_CORRUPT_BKPT;
- goto abort_due_to_error;
+ if( aOffset[0] > 98307 || aOffset[0] > pC->payloadSize ){
+ goto op_column_corrupt;
}
- }else if( offset>0 ){ /*OPTIMIZATION-IF-TRUE*/
- /* The following goto is an optimization. It can be omitted and
- ** everything will still work. But OP_Column is measurably faster
- ** by skipping the subsequent conditional, which is always true.
+ }else{
+ /* This is an optimization. By skipping over the first few tests
+ ** (ex: pC->nHdrParsed<=p2) in the next section, we achieve a
+ ** measurable performance gain.
+ **
+ ** This branch is taken even if aOffset[0]==0. Such a record is never
+ ** generated by SQLite, and could be considered corruption, but we
+ ** accept it for historical reasons. When aOffset[0]==0, the code this
+ ** branch jumps to reads past the end of the record, but never more
+ ** than a few bytes. Even if the record occurs at the end of the page
+ ** content area, the "page header" comes after the page content and so
+ ** this overread is harmless. Similar overreads can occur for a corrupt
+ ** database file.
*/
zData = pC->aRow;
assert( pC->nHdrParsed<=p2 ); /* Conditional skipped */
+ testcase( aOffset[0]==0 );
goto op_column_read_header;
}
}
@@ -79857,7 +82505,7 @@ case OP_Column: {
/* Make sure zData points to enough of the record to cover the header. */
if( pC->aRow==0 ){
memset(&sMem, 0, sizeof(sMem));
- rc = sqlite3VdbeMemFromBtree(pCrsr, 0, aOffset[0], !pC->isTable, &sMem);
+ rc = sqlite3VdbeMemFromBtree(pC->uc.pCursor, 0, aOffset[0], &sMem);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
zData = (u8*)sMem.z;
}else{
@@ -79870,6 +82518,7 @@ case OP_Column: {
offset64 = aOffset[i];
zHdr = zData + pC->iHdrOffset;
zEndHdr = zData + aOffset[0];
+ testcase( zHdr>=zEndHdr );
do{
if( (t = zHdr[0])<0x80 ){
zHdr++;
@@ -79890,9 +82539,13 @@ case OP_Column: {
if( (zHdr>=zEndHdr && (zHdr>zEndHdr || offset64!=pC->payloadSize))
|| (offset64 > pC->payloadSize)
){
- if( pC->aRow==0 ) sqlite3VdbeMemRelease(&sMem);
- rc = SQLITE_CORRUPT_BKPT;
- goto abort_due_to_error;
+ if( aOffset[0]==0 ){
+ i = 0;
+ zHdr = zEndHdr;
+ }else{
+ if( pC->aRow==0 ) sqlite3VdbeMemRelease(&sMem);
+ goto op_column_corrupt;
+ }
}
pC->nHdrParsed = i;
@@ -79966,12 +82619,16 @@ case OP_Column: {
** 2. the length(X) function if X is a blob, and
** 3. if the content length is zero.
** So we might as well use bogus content rather than reading
- ** content from disk. */
- static u8 aZero[8]; /* This is the bogus content */
+ ** content from disk.
+ **
+ ** Although sqlite3VdbeSerialGet() may read at most 8 bytes from the
+ ** buffer passed to it, debugging function VdbeMemPrettyPrint() may
+ ** read up to 16. So 16 bytes of bogus content is supplied.
+ */
+ static u8 aZero[16]; /* This is the bogus content */
sqlite3VdbeSerialGet(aZero, t, pDest);
}else{
- rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, !pC->isTable,
- pDest);
+ rc = sqlite3VdbeMemFromBtree(pC->uc.pCursor, aOffset[p2], len, pDest);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
sqlite3VdbeSerialGet((const u8*)pDest->z, t, pDest);
pDest->flags &= ~MEM_Ephem;
@@ -79982,6 +82639,15 @@ case OP_Column: {
UPDATE_MAX_BLOBSIZE(pDest);
REGISTER_TRACE(pOp->p3, pDest);
break;
+
+op_column_corrupt:
+ if( aOp[0].p3>0 ){
+ pOp = &aOp[aOp[0].p3-1];
+ break;
+ }else{
+ rc = SQLITE_CORRUPT_BKPT;
+ goto abort_due_to_error;
+ }
}
/* Opcode: Affinity P1 P2 * P4 *
@@ -79989,24 +82655,24 @@ case OP_Column: {
**
** 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
+** P4 is a string that is P2 characters long. The N-th character of the
+** string indicates the column affinity that should be used for the N-th
** memory cell in the range.
*/
case OP_Affinity: {
const char *zAffinity; /* The affinity to be applied */
- char cAff; /* A single character of affinity */
zAffinity = pOp->p4.z;
assert( zAffinity!=0 );
+ assert( pOp->p2>0 );
assert( zAffinity[pOp->p2]==0 );
pIn1 = &aMem[pOp->p1];
- while( (cAff = *(zAffinity++))!=0 ){
+ do{
assert( pIn1 <= &p->aMem[(p->nMem+1 - p->nCursor)] );
assert( memIsValid(pIn1) );
- applyAffinity(pIn1, cAff, encoding);
+ applyAffinity(pIn1, *(zAffinity++), encoding);
pIn1++;
- }
+ }while( zAffinity[0] );
break;
}
@@ -80017,8 +82683,8 @@ case OP_Affinity: {
** use as a data record in a database table or as a key
** in an index. The OP_Column opcode can decode the record later.
**
-** 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
+** P4 may be a string that is P2 characters long. The N-th character of the
+** string indicates the column affinity that should be used for the N-th
** field of the index key.
**
** The mapping from character to affinity is given by the SQLITE_AFF_
@@ -80086,15 +82752,38 @@ case OP_MakeRecord: {
}while( zAffinity[0] );
}
+#ifdef SQLITE_ENABLE_NULL_TRIM
+ /* NULLs can be safely trimmed from the end of the record, as long as
+ ** as the schema format is 2 or more and none of the omitted columns
+ ** have a non-NULL default value. Also, the record must be left with
+ ** at least one field. If P5>0 then it will be one more than the
+ ** index of the right-most column with a non-NULL default value */
+ if( pOp->p5 ){
+ while( (pLast->flags & MEM_Null)!=0 && nField>pOp->p5 ){
+ pLast--;
+ nField--;
+ }
+ }
+#endif
+
/* Loop through the elements that will make up the record to figure
** out how much space is required for the new record.
*/
pRec = pLast;
do{
assert( memIsValid(pRec) );
- pRec->uTemp = serial_type = sqlite3VdbeSerialType(pRec, file_format, &len);
+ serial_type = sqlite3VdbeSerialType(pRec, file_format, &len);
if( pRec->flags & MEM_Zero ){
- if( nData ){
+ if( serial_type==0 ){
+ /* Values with MEM_Null and MEM_Zero are created by xColumn virtual
+ ** table methods that never invoke sqlite3_result_xxxxx() while
+ ** computing an unchanging column value in an UPDATE statement.
+ ** Give such values a special internal-use-only serial-type of 10
+ ** so that they can be passed through to xUpdate and have
+ ** a true sqlite3_value_nochange(). */
+ assert( pOp->p5==OPFLAG_NOCHNG_MAGIC || CORRUPT_DB );
+ serial_type = 10;
+ }else if( nData ){
if( sqlite3VdbeMemExpandBlob(pRec) ) goto no_mem;
}else{
nZero += pRec->u.nZero;
@@ -80105,6 +82794,7 @@ case OP_MakeRecord: {
testcase( serial_type==127 );
testcase( serial_type==128 );
nHdr += serial_type<=127 ? 1 : sqlite3VarintLen(serial_type);
+ pRec->uTemp = serial_type;
if( pRec==pData0 ) break;
pRec--;
}while(1);
@@ -80163,7 +82853,6 @@ case OP_MakeRecord: {
pOut->u.nZero = nZero;
pOut->flags |= MEM_Zero;
}
- pOut->enc = SQLITE_UTF8; /* In case the blob is ever converted to text */
REGISTER_TRACE(pOp->p3, pOut);
UPDATE_MAX_BLOBSIZE(pOut);
break;
@@ -80309,7 +82998,7 @@ case OP_Savepoint: {
int isSchemaChange;
iSavepoint = db->nSavepoint - iSavepoint - 1;
if( p1==SAVEPOINT_ROLLBACK ){
- isSchemaChange = (db->flags & SQLITE_InternChanges)!=0;
+ isSchemaChange = (db->mDbFlags & DBFLAG_SchemaChange)!=0;
for(ii=0; iinDb; ii++){
rc = sqlite3BtreeTripAllCursors(db->aDb[ii].pBt,
SQLITE_ABORT_ROLLBACK,
@@ -80328,7 +83017,7 @@ case OP_Savepoint: {
if( isSchemaChange ){
sqlite3ExpirePreparedStatements(db);
sqlite3ResetAllSchemasOfConnection(db);
- db->flags = (db->flags | SQLITE_InternChanges);
+ db->mDbFlags |= DBFLAG_SchemaChange;
}
}
@@ -80608,7 +83297,7 @@ case OP_SetCookie: {
if( pOp->p2==BTREE_SCHEMA_VERSION ){
/* When the schema cookie changes, record the new cookie internally */
pDb->pSchema->schema_cookie = pOp->p3;
- db->flags |= SQLITE_InternChanges;
+ db->mDbFlags |= DBFLAG_SchemaChange;
}else if( pOp->p2==BTREE_FILE_FORMAT ){
/* Record changes in the file format */
pDb->pSchema->file_format = pOp->p3;
@@ -80747,7 +83436,7 @@ case OP_OpenWrite:
assert( (pIn2->flags & MEM_Int)!=0 );
sqlite3VdbeMemIntegerify(pIn2);
p2 = (int)pIn2->u.i;
- /* The p2 value always comes from a prior OP_CreateTable opcode and
+ /* The p2 value always comes from a prior OP_CreateBtree opcode and
** that opcode will always set the p2 value to 2 or more or else fail.
** If there were a failure, the prepared statement would have halted
** before reaching this instruction. */
@@ -80757,7 +83446,7 @@ case OP_OpenWrite:
pKeyInfo = pOp->p4.pKeyInfo;
assert( pKeyInfo->enc==ENC(db) );
assert( pKeyInfo->db==db );
- nField = pKeyInfo->nField+pKeyInfo->nXField;
+ nField = pKeyInfo->nAllField;
}else if( pOp->p4type==P4_INT32 ){
nField = pOp->p4.i;
}
@@ -80793,6 +83482,37 @@ case OP_OpenWrite:
break;
}
+/* Opcode: OpenDup P1 P2 * * *
+**
+** Open a new cursor P1 that points to the same ephemeral table as
+** cursor P2. The P2 cursor must have been opened by a prior OP_OpenEphemeral
+** opcode. Only ephemeral cursors may be duplicated.
+**
+** Duplicate ephemeral cursors are used for self-joins of materialized views.
+*/
+case OP_OpenDup: {
+ VdbeCursor *pOrig; /* The original cursor to be duplicated */
+ VdbeCursor *pCx; /* The new cursor */
+
+ pOrig = p->apCsr[pOp->p2];
+ assert( pOrig->pBtx!=0 ); /* Only ephemeral cursors can be duplicated */
+
+ pCx = allocateCursor(p, pOp->p1, pOrig->nField, -1, CURTYPE_BTREE);
+ if( pCx==0 ) goto no_mem;
+ pCx->nullRow = 1;
+ pCx->isEphemeral = 1;
+ pCx->pKeyInfo = pOrig->pKeyInfo;
+ pCx->isTable = pOrig->isTable;
+ rc = sqlite3BtreeCursor(pOrig->pBtx, MASTER_ROOT, BTREE_WRCSR,
+ pCx->pKeyInfo, pCx->uc.pCursor);
+ /* The sqlite3BtreeCursor() routine can only fail for the first cursor
+ ** opened for a database. Since there is already an open cursor when this
+ ** opcode is run, the sqlite3BtreeCursor() cannot fail */
+ assert( rc==SQLITE_OK );
+ break;
+}
+
+
/* Opcode: OpenEphemeral P1 P2 * P4 P5
** Synopsis: nColumn=P2
**
@@ -80836,10 +83556,10 @@ case OP_OpenEphemeral: {
if( pCx==0 ) goto no_mem;
pCx->nullRow = 1;
pCx->isEphemeral = 1;
- rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBt,
+ rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBtx,
BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags);
if( rc==SQLITE_OK ){
- rc = sqlite3BtreeBeginTrans(pCx->pBt, 1);
+ rc = sqlite3BtreeBeginTrans(pCx->pBtx, 1);
}
if( rc==SQLITE_OK ){
/* If a transient index is required, create it by calling
@@ -80847,21 +83567,20 @@ case OP_OpenEphemeral: {
** opening it. If a transient table is required, just use the
** automatically created table with root-page 1 (an BLOB_INTKEY table).
*/
- if( (pKeyInfo = pOp->p4.pKeyInfo)!=0 ){
+ if( (pCx->pKeyInfo = pKeyInfo = pOp->p4.pKeyInfo)!=0 ){
int pgno;
assert( pOp->p4type==P4_KEYINFO );
- rc = sqlite3BtreeCreateTable(pCx->pBt, &pgno, BTREE_BLOBKEY | pOp->p5);
+ rc = sqlite3BtreeCreateTable(pCx->pBtx, &pgno, BTREE_BLOBKEY | pOp->p5);
if( rc==SQLITE_OK ){
assert( pgno==MASTER_ROOT+1 );
assert( pKeyInfo->db==db );
assert( pKeyInfo->enc==ENC(db) );
- pCx->pKeyInfo = pKeyInfo;
- rc = sqlite3BtreeCursor(pCx->pBt, pgno, BTREE_WRCSR,
+ rc = sqlite3BtreeCursor(pCx->pBtx, pgno, BTREE_WRCSR,
pKeyInfo, pCx->uc.pCursor);
}
pCx->isTable = 0;
}else{
- rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, BTREE_WRCSR,
+ rc = sqlite3BtreeCursor(pCx->pBtx, MASTER_ROOT, BTREE_WRCSR,
0, pCx->uc.pCursor);
pCx->isTable = 1;
}
@@ -80938,8 +83657,13 @@ case OP_OpenPseudo: {
pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, CURTYPE_PSEUDO);
if( pCx==0 ) goto no_mem;
pCx->nullRow = 1;
- pCx->uc.pseudoTableReg = pOp->p2;
+ pCx->seekResult = pOp->p2;
pCx->isTable = 1;
+ /* Give this pseudo-cursor a fake BtCursor pointer so that pCx
+ ** can be safely passed to sqlite3VdbeCursorMoveto(). This avoids a test
+ ** for pCx->eCurType==CURTYPE_BTREE inside of sqlite3VdbeCursorMoveto()
+ ** which is a performance optimization */
+ pCx->uc.pCursor = sqlite3BtreeFakeValidCursor();
assert( pOp->p5==0 );
break;
}
@@ -81093,7 +83817,8 @@ case OP_SeekGT: { /* jump, in3 */
if( pC->isTable ){
/* The BTREE_SEEK_EQ flag is only set on index cursors */
- assert( sqlite3BtreeCursorHasHint(pC->uc.pCursor, BTREE_SEEK_EQ)==0 );
+ assert( sqlite3BtreeCursorHasHint(pC->uc.pCursor, BTREE_SEEK_EQ)==0
+ || CORRUPT_DB );
/* The input value in P3 might be of any type: integer, real, string,
** blob, or NULL. But it needs to be an integer before we can do
@@ -81198,8 +83923,15 @@ case OP_SeekGT: { /* jump, in3 */
if( oc>=OP_SeekGE ){ assert( oc==OP_SeekGE || oc==OP_SeekGT );
if( res<0 || (res==0 && oc==OP_SeekGT) ){
res = 0;
- rc = sqlite3BtreeNext(pC->uc.pCursor, &res);
- if( rc!=SQLITE_OK ) goto abort_due_to_error;
+ rc = sqlite3BtreeNext(pC->uc.pCursor, 0);
+ if( rc!=SQLITE_OK ){
+ if( rc==SQLITE_DONE ){
+ rc = SQLITE_OK;
+ res = 1;
+ }else{
+ goto abort_due_to_error;
+ }
+ }
}else{
res = 0;
}
@@ -81207,8 +83939,15 @@ case OP_SeekGT: { /* jump, in3 */
assert( oc==OP_SeekLT || oc==OP_SeekLE );
if( res>0 || (res==0 && oc==OP_SeekLT) ){
res = 0;
- rc = sqlite3BtreePrevious(pC->uc.pCursor, &res);
- if( rc!=SQLITE_OK ) goto abort_due_to_error;
+ rc = sqlite3BtreePrevious(pC->uc.pCursor, 0);
+ if( rc!=SQLITE_OK ){
+ if( rc==SQLITE_DONE ){
+ rc = SQLITE_OK;
+ res = 1;
+ }else{
+ goto abort_due_to_error;
+ }
+ }
}else{
/* res might be negative because the table is empty. Check to
** see if this is the case.
@@ -81295,10 +84034,9 @@ case OP_Found: { /* jump, in3 */
int ii;
VdbeCursor *pC;
int res;
- char *pFree;
+ UnpackedRecord *pFree;
UnpackedRecord *pIdxKey;
UnpackedRecord r;
- char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*4 + 7];
#ifdef SQLITE_TEST
if( pOp->opcode!=OP_NoConflict ) sqlite3_found_count++;
@@ -81315,7 +84053,6 @@ case OP_Found: { /* jump, in3 */
assert( pC->eCurType==CURTYPE_BTREE );
assert( pC->uc.pCursor!=0 );
assert( pC->isTable==0 );
- pFree = 0;
if( pOp->p4.i>0 ){
r.pKeyInfo = pC->pKeyInfo;
r.nField = (u16)pOp->p4.i;
@@ -81328,13 +84065,14 @@ case OP_Found: { /* jump, in3 */
}
#endif
pIdxKey = &r;
+ pFree = 0;
}else{
- pIdxKey = sqlite3VdbeAllocUnpackedRecord(
- pC->pKeyInfo, aTempRec, sizeof(aTempRec), &pFree
- );
- if( pIdxKey==0 ) goto no_mem;
assert( pIn3->flags & MEM_Blob );
- (void)ExpandBlob(pIn3);
+ rc = ExpandBlob(pIn3);
+ assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
+ if( rc ) goto no_mem;
+ pFree = pIdxKey = sqlite3VdbeAllocUnpackedRecord(pC->pKeyInfo);
+ if( pIdxKey==0 ) goto no_mem;
sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z, pIdxKey);
}
pIdxKey->default_rc = 0;
@@ -81351,7 +84089,7 @@ case OP_Found: { /* jump, in3 */
}
}
rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, pIdxKey, 0, 0, &res);
- sqlite3DbFree(db, pFree);
+ if( pFree ) sqlite3DbFreeNN(db, pFree);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
@@ -81578,7 +84316,7 @@ case OP_NewRowid: { /* out2 */
sqlite3VdbeMemIntegerify(pMem);
assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */
if( pMem->u.i==MAX_ROWID || pC->useRandomRowid ){
- rc = SQLITE_FULL; /* IMP: R-12275-61338 */
+ rc = SQLITE_FULL; /* IMP: R-17817-00630 */
goto abort_due_to_error;
}
if( vu.i+1 ){
@@ -81630,15 +84368,10 @@ case OP_NewRowid: { /* out2 */
** then rowid is stored for subsequent return by the
** sqlite3_last_insert_rowid() function (otherwise it is unmodified).
**
-** If the OPFLAG_USESEEKRESULT flag of P5 is set and if the result of
-** the last seek operation (OP_NotExists or OP_SeekRowid) was a success,
-** then this
-** operation will not attempt to find the appropriate row before doing
-** the insert but will instead overwrite the row that the cursor is
-** currently pointing to. Presumably, the prior OP_NotExists or
-** OP_SeekRowid opcode
-** has already positioned the cursor correctly. This is an optimization
-** that boosts performance by avoiding redundant seeks.
+** If the OPFLAG_USESEEKRESULT flag of P5 is set, the implementation might
+** run faster by avoiding an unnecessary seek on cursor P1. However,
+** the OPFLAG_USESEEKRESULT flag must only be set if there have been no prior
+** seeks on the cursor or if the most recent seek used a key equal to P3.
**
** If the OPFLAG_ISUPDATE flag is set, then this opcode is part of an
** UPDATE operation. Otherwise (if the flag is clear) then this opcode
@@ -81672,10 +84405,8 @@ case OP_InsertInt: {
int seekResult; /* Result of prior seek or 0 if no USESEEKRESULT flag */
const char *zDb; /* database name - used by the update hook */
Table *pTab; /* Table structure - used by update and pre-update hooks */
- int op; /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */
BtreePayload x; /* Payload to be inserted */
- op = 0;
pData = &aMem[pOp->p2];
assert( pOp->p1>=0 && pOp->p1nCursor );
assert( memIsValid(pData) );
@@ -81683,7 +84414,7 @@ case OP_InsertInt: {
assert( pC!=0 );
assert( pC->eCurType==CURTYPE_BTREE );
assert( pC->uc.pCursor!=0 );
- assert( pC->isTable );
+ assert( (pOp->p5 & OPFLAG_ISNOOP) || pC->isTable );
assert( pOp->p4type==P4_TABLE || pOp->p4type>=P4_STATIC );
REGISTER_TRACE(pOp->p2, pData);
@@ -81699,37 +84430,34 @@ case OP_InsertInt: {
}
if( pOp->p4type==P4_TABLE && HAS_UPDATE_HOOK(db) ){
- assert( pC->isTable );
assert( pC->iDb>=0 );
zDb = db->aDb[pC->iDb].zDbSName;
pTab = pOp->p4.pTab;
- assert( HasRowid(pTab) );
- op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT);
+ assert( (pOp->p5 & OPFLAG_ISNOOP) || HasRowid(pTab) );
}else{
- pTab = 0; /* Not needed. Silence a comiler warning. */
+ pTab = 0;
zDb = 0; /* Not needed. Silence a compiler warning. */
}
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
/* Invoke the pre-update hook, if any */
- if( db->xPreUpdateCallback
- && pOp->p4type==P4_TABLE
- && !(pOp->p5 & OPFLAG_ISUPDATE)
- ){
- sqlite3VdbePreUpdateHook(p, pC, SQLITE_INSERT, zDb, pTab, x.nKey, pOp->p2);
+ if( pTab ){
+ if( db->xPreUpdateCallback && !(pOp->p5 & OPFLAG_ISUPDATE) ){
+ sqlite3VdbePreUpdateHook(p, pC, SQLITE_INSERT, zDb, pTab, x.nKey,pOp->p2);
+ }
+ if( db->xUpdateCallback==0 || pTab->aCol==0 ){
+ /* Prevent post-update hook from running in cases when it should not */
+ pTab = 0;
+ }
}
+ if( pOp->p5 & OPFLAG_ISNOOP ) break;
#endif
if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
- if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = lastRowid = x.nKey;
- if( pData->flags & MEM_Null ){
- x.pData = 0;
- x.nData = 0;
- }else{
- assert( pData->flags & (MEM_Blob|MEM_Str) );
- x.pData = pData->z;
- x.nData = pData->n;
- }
+ if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = x.nKey;
+ assert( pData->flags & (MEM_Blob|MEM_Str) );
+ x.pData = pData->z;
+ x.nData = pData->n;
seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0);
if( pData->flags & MEM_Zero ){
x.nZero = pData->u.nZero;
@@ -81738,15 +84466,19 @@ case OP_InsertInt: {
}
x.pKey = 0;
rc = sqlite3BtreeInsert(pC->uc.pCursor, &x,
- (pOp->p5 & OPFLAG_APPEND)!=0, seekResult
+ (pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION)), seekResult
);
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
/* Invoke the update-hook if required. */
if( rc ) goto abort_due_to_error;
- if( db->xUpdateCallback && op ){
- db->xUpdateCallback(db->pUpdateArg, op, zDb, pTab->zName, x.nKey);
+ if( pTab ){
+ assert( db->xUpdateCallback!=0 );
+ assert( pTab->aCol!=0 );
+ db->xUpdateCallback(db->pUpdateArg,
+ (pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT,
+ zDb, pTab->zName, x.nKey);
}
break;
}
@@ -81830,8 +84562,11 @@ case OP_Delete: {
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
/* Invoke the pre-update-hook if required. */
- if( db->xPreUpdateCallback && pOp->p4.pTab && HasRowid(pTab) ){
- assert( !(opflags & OPFLAG_ISUPDATE) || (aMem[pOp->p3].flags & MEM_Int) );
+ if( db->xPreUpdateCallback && pOp->p4.pTab ){
+ assert( !(opflags & OPFLAG_ISUPDATE)
+ || HasRowid(pTab)==0
+ || (aMem[pOp->p3].flags & MEM_Int)
+ );
sqlite3VdbePreUpdateHook(p, pC,
(opflags & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_DELETE,
zDb, pTab, pC->movetoTarget,
@@ -81862,6 +84597,7 @@ case OP_Delete: {
rc = sqlite3BtreeDelete(pC->uc.pCursor, pOp->p5);
pC->cacheStatus = CACHE_STALE;
+ pC->seekResult = 0;
if( rc ) goto abort_due_to_error;
/* Invoke the update-hook if required. */
@@ -81948,50 +84684,51 @@ case OP_SorterData: {
break;
}
-/* Opcode: RowData P1 P2 * * *
+/* Opcode: RowData P1 P2 P3 * *
** Synopsis: r[P2]=data
**
-** Write into register P2 the complete row data for cursor P1.
+** Write into register P2 the complete row content for the row at
+** which cursor P1 is currently pointing.
** There is no interpretation of the data.
** It is just copied onto the P2 register exactly as
** it is found in the database file.
**
+** If cursor P1 is an index, then the content is the key of the row.
+** If cursor P2 is a table, then the content extracted is the data.
+**
** If the P1 cursor must be pointing to a valid row (not a NULL row)
** of a real table, not a pseudo-table.
-*/
-/* Opcode: RowKey P1 P2 * * *
-** Synopsis: r[P2]=key
**
-** Write into register P2 the complete row key for cursor P1.
-** There is no interpretation of the data.
-** The key is copied onto the P2 register exactly as
-** it is found in the database file.
+** If P3!=0 then this opcode is allowed to make an ephermeral pointer
+** into the database page. That means that the content of the output
+** register will be invalidated as soon as the cursor moves - including
+** moves caused by other cursors that "save" the the current cursors
+** position in order that they can write to the same table. If P3==0
+** then a copy of the data is made into memory. P3!=0 is faster, but
+** P3==0 is safer.
**
-** If the P1 cursor must be pointing to a valid row (not a NULL row)
-** of a real table, not a pseudo-table.
+** If P3!=0 then the content of the P2 register is unsuitable for use
+** in OP_Result and any OP_Result will invalidate the P2 register content.
+** The P2 register content is invalidated by opcodes like OP_Function or
+** by any use of another cursor pointing to the same table.
*/
-case OP_RowKey:
case OP_RowData: {
VdbeCursor *pC;
BtCursor *pCrsr;
u32 n;
- pOut = &aMem[pOp->p2];
- memAboutToChange(p, pOut);
+ pOut = out2Prerelease(p, pOp);
- /* Note that RowKey and RowData are really exactly the same instruction */
assert( pOp->p1>=0 && pOp->p1nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
assert( pC->eCurType==CURTYPE_BTREE );
assert( isSorter(pC)==0 );
- assert( pC->isTable || pOp->opcode!=OP_RowData );
- assert( pC->isTable==0 || pOp->opcode==OP_RowData );
assert( pC->nullRow==0 );
assert( pC->uc.pCursor!=0 );
pCrsr = pC->uc.pCursor;
- /* The OP_RowKey and OP_RowData opcodes always follow OP_NotExists or
+ /* The OP_RowData opcodes always follow OP_NotExists or
** OP_SeekRowid or OP_Rewind/Op_Next with no intervening instructions
** that might invalidate the cursor.
** If this where not the case, on of the following assert()s
@@ -82011,18 +84748,9 @@ case OP_RowData: {
goto too_big;
}
testcase( n==0 );
- if( sqlite3VdbeMemClearAndResize(pOut, MAX(n,32)) ){
- goto no_mem;
- }
- pOut->n = n;
- MemSetTypeFlag(pOut, MEM_Blob);
- if( pC->isTable==0 ){
- rc = sqlite3BtreeKey(pCrsr, 0, n, pOut->z);
- }else{
- rc = sqlite3BtreeData(pCrsr, 0, n, pOut->z);
- }
+ rc = sqlite3VdbeMemFromBtree(pCrsr, 0, n, pOut);
if( rc ) goto abort_due_to_error;
- pOut->enc = SQLITE_UTF8; /* In case the blob is ever cast to text */
+ if( !pOp->p3 ) Deephemeralize(pOut);
UPDATE_MAX_BLOBSIZE(pOut);
REGISTER_TRACE(pOp->p2, pOut);
break;
@@ -82100,7 +84828,17 @@ case OP_NullRow: {
break;
}
-/* Opcode: Last P1 P2 P3 * *
+/* Opcode: SeekEnd P1 * * * *
+**
+** Position cursor P1 at the end of the btree for the purpose of
+** appending a new entry onto the btree.
+**
+** It is assumed that the cursor is used only for appending and so
+** if the cursor is valid, then the cursor must already be pointing
+** at the end of the btree and so no changes are made to
+** the cursor.
+*/
+/* Opcode: Last P1 P2 * * *
**
** The next use of the Rowid or Column or Prev instruction for P1
** will refer to the last entry in the database table or index.
@@ -82112,6 +84850,7 @@ case OP_NullRow: {
** from the end toward the beginning. In other words, the cursor is
** configured to use Prev, not Next.
*/
+case OP_SeekEnd:
case OP_Last: { /* jump */
VdbeCursor *pC;
BtCursor *pCrsr;
@@ -82124,14 +84863,20 @@ case OP_Last: { /* jump */
pCrsr = pC->uc.pCursor;
res = 0;
assert( pCrsr!=0 );
+#ifdef SQLITE_DEBUG
+ pC->seekOp = pOp->opcode;
+#endif
+ if( pOp->opcode==OP_SeekEnd ){
+ assert( pOp->p2==0 );
+ pC->seekResult = -1;
+ if( sqlite3BtreeCursorIsValidNN(pCrsr) ){
+ break;
+ }
+ }
rc = sqlite3BtreeLast(pCrsr, &res);
pC->nullRow = (u8)res;
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
- pC->seekResult = pOp->p3;
-#ifdef SQLITE_DEBUG
- pC->seekOp = OP_Last;
-#endif
if( rc ) goto abort_due_to_error;
if( pOp->p2>0 ){
VdbeBranchTaken(res!=0,2);
@@ -82140,7 +84885,43 @@ case OP_Last: { /* jump */
break;
}
+/* Opcode: IfSmaller P1 P2 P3 * *
+**
+** Estimate the number of rows in the table P1. Jump to P2 if that
+** estimate is less than approximately 2**(0.1*P3).
+*/
+case OP_IfSmaller: { /* jump */
+ VdbeCursor *pC;
+ BtCursor *pCrsr;
+ int res;
+ i64 sz;
+ assert( pOp->p1>=0 && pOp->p1nCursor );
+ pC = p->apCsr[pOp->p1];
+ assert( pC!=0 );
+ pCrsr = pC->uc.pCursor;
+ assert( pCrsr );
+ rc = sqlite3BtreeFirst(pCrsr, &res);
+ if( rc ) goto abort_due_to_error;
+ if( res==0 ){
+ sz = sqlite3BtreeRowCountEst(pCrsr);
+ if( ALWAYS(sz>=0) && sqlite3LogEst((u64)sz)p3 ) res = 1;
+ }
+ VdbeBranchTaken(res!=0,2);
+ if( res ) goto jump_to_p2;
+ break;
+}
+
+
+/* Opcode: SorterSort P1 P2 * * *
+**
+** After all records have been inserted into the Sorter object
+** identified by P1, invoke this opcode to actually do the sorting.
+** Jump to P2 if there are no records to be sorted.
+**
+** This opcode is an alias for OP_Sort and OP_Rewind that is used
+** for Sorter objects.
+*/
/* Opcode: Sort P1 P2 * * *
**
** This opcode does exactly the same thing as OP_Rewind except that
@@ -82268,14 +85049,19 @@ case OP_Rewind: { /* jump */
** This opcode works just like Prev except that if cursor P1 is not
** open it behaves a no-op.
*/
+/* Opcode: SorterNext P1 P2 * * P5
+**
+** This opcode works just like OP_Next except that P1 must be a
+** sorter object for which the OP_SorterSort opcode has been
+** invoked. This opcode advances the cursor to the next sorted
+** record, or jumps to P2 if there are no more sorted records.
+*/
case OP_SorterNext: { /* jump */
VdbeCursor *pC;
- int res;
pC = p->apCsr[pOp->p1];
assert( isSorter(pC) );
- res = 0;
- rc = sqlite3VdbeSorterNext(db, pC, &res);
+ rc = sqlite3VdbeSorterNext(db, pC);
goto next_tail;
case OP_PrevIfOpen: /* jump */
case OP_NextIfOpen: /* jump */
@@ -82286,12 +85072,9 @@ case OP_Next: /* jump */
assert( pOp->p1>=0 && pOp->p1nCursor );
assert( pOp->p5aCounter) );
pC = p->apCsr[pOp->p1];
- res = pOp->p3;
assert( pC!=0 );
assert( pC->deferredMoveto==0 );
assert( pC->eCurType==CURTYPE_BTREE );
- assert( res==0 || (res==1 && pC->isTable==0) );
- testcase( res==1 );
assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext );
assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious );
assert( pOp->opcode!=OP_NextIfOpen || pOp->p4.xAdvance==sqlite3BtreeNext );
@@ -82306,45 +85089,59 @@ case OP_Next: /* jump */
|| pC->seekOp==OP_SeekLT || pC->seekOp==OP_SeekLE
|| pC->seekOp==OP_Last );
- rc = pOp->p4.xAdvance(pC->uc.pCursor, &res);
+ rc = pOp->p4.xAdvance(pC->uc.pCursor, pOp->p3);
next_tail:
pC->cacheStatus = CACHE_STALE;
- VdbeBranchTaken(res==0,2);
- if( rc ) goto abort_due_to_error;
- if( res==0 ){
+ VdbeBranchTaken(rc==SQLITE_OK,2);
+ if( rc==SQLITE_OK ){
pC->nullRow = 0;
p->aCounter[pOp->p5]++;
#ifdef SQLITE_TEST
sqlite3_search_count++;
#endif
goto jump_to_p2_and_check_for_interrupt;
- }else{
- pC->nullRow = 1;
}
+ if( rc!=SQLITE_DONE ) goto abort_due_to_error;
+ rc = SQLITE_OK;
+ pC->nullRow = 1;
goto check_for_interrupt;
}
-/* Opcode: IdxInsert P1 P2 P3 * P5
+/* Opcode: IdxInsert P1 P2 P3 P4 P5
** Synopsis: key=r[P2]
**
** Register P2 holds an SQL index key made using the
** MakeRecord instructions. This opcode writes that key
** into the index P1. Data for the entry is nil.
**
-** P3 is a flag that provides a hint to the b-tree layer that this
-** insert is likely to be an append.
+** If P4 is not zero, then it is the number of values in the unpacked
+** key of reg(P2). In that case, P3 is the index of the first register
+** for the unpacked key. The availability of the unpacked key can sometimes
+** be an optimization.
+**
+** If P5 has the OPFLAG_APPEND bit set, that is a hint to the b-tree layer
+** that this insert is likely to be an append.
**
** If P5 has the OPFLAG_NCHANGE bit set, then the change counter is
** incremented by this instruction. If the OPFLAG_NCHANGE bit is clear,
** then the change counter is unchanged.
**
-** If P5 has the OPFLAG_USESEEKRESULT bit set, then the cursor must have
-** just done a seek to the spot where the new entry is to be inserted.
-** This flag avoids doing an extra seek.
+** If the OPFLAG_USESEEKRESULT flag of P5 is set, the implementation might
+** run faster by avoiding an unnecessary seek on cursor P1. However,
+** the OPFLAG_USESEEKRESULT flag must only be set if there have been no prior
+** seeks on the cursor or if the most recent seek used a key equivalent
+** to P2.
**
** This instruction only works for indices. The equivalent instruction
** for tables is OP_Insert.
*/
+/* Opcode: SorterInsert P1 P2 * * *
+** Synopsis: key=r[P2]
+**
+** Register P2 holds an SQL index key made using the
+** MakeRecord instructions. This opcode writes that key
+** into the sorter P1. Data for the entry is nil.
+*/
case OP_SorterInsert: /* in2 */
case OP_IdxInsert: { /* in2 */
VdbeCursor *pC;
@@ -82366,7 +85163,10 @@ case OP_IdxInsert: { /* in2 */
}else{
x.nKey = pIn2->n;
x.pKey = pIn2->z;
- rc = sqlite3BtreeInsert(pC->uc.pCursor, &x, pOp->p3,
+ x.aMem = aMem + pOp->p3;
+ x.nMem = (u16)pOp->p4.i;
+ rc = sqlite3BtreeInsert(pC->uc.pCursor, &x,
+ (pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION)),
((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0)
);
assert( pC->deferredMoveto==0 );
@@ -82410,11 +85210,12 @@ case OP_IdxDelete: {
}
assert( pC->deferredMoveto==0 );
pC->cacheStatus = CACHE_STALE;
+ pC->seekResult = 0;
break;
}
-/* Opcode: Seek P1 * P3 P4 *
-** Synopsis: Move P3 to P1.rowid
+/* Opcode: DeferredSeek P1 * P3 P4 *
+** Synopsis: Move P3 to P1.rowid if needed
**
** P1 is an open index cursor and P3 is a cursor on the corresponding
** table. This opcode does a deferred seek of the P3 table cursor
@@ -82441,11 +85242,11 @@ case OP_IdxDelete: {
**
** See also: Rowid, MakeRecord.
*/
-case OP_Seek:
-case OP_IdxRowid: { /* out2 */
- VdbeCursor *pC; /* The P1 index cursor */
- VdbeCursor *pTabCur; /* The P2 table cursor (OP_Seek only) */
- i64 rowid; /* Rowid that P1 current points to */
+case OP_DeferredSeek:
+case OP_IdxRowid: { /* out2 */
+ VdbeCursor *pC; /* The P1 index cursor */
+ VdbeCursor *pTabCur; /* The P2 table cursor (OP_DeferredSeek only) */
+ i64 rowid; /* Rowid that P1 current points to */
assert( pOp->p1>=0 && pOp->p1nCursor );
pC = p->apCsr[pOp->p1];
@@ -82471,7 +85272,7 @@ case OP_IdxRowid: { /* out2 */
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
- if( pOp->opcode==OP_Seek ){
+ if( pOp->opcode==OP_DeferredSeek ){
assert( pOp->p3>=0 && pOp->p3nCursor );
pTabCur = p->apCsr[pOp->p3];
assert( pTabCur!=0 );
@@ -82487,7 +85288,6 @@ case OP_IdxRowid: { /* out2 */
}else{
pOut = out2Prerelease(p, pOp);
pOut->u.i = rowid;
- pOut->flags = MEM_Int;
}
}else{
assert( pOp->opcode==OP_IdxRowid );
@@ -82599,10 +85399,17 @@ case OP_IdxGE: { /* jump */
** might be moved into the newly deleted root page in order to keep all
** root pages contiguous at the beginning of the database. The former
** value of the root page that moved - its value before the move occurred -
-** is stored in register P2. If no page
-** movement was required (because the table being dropped was already
-** the last one in the database) then a zero is stored in register P2.
-** If AUTOVACUUM is disabled then a zero is stored in register P2.
+** is stored in register P2. If no page movement was required (because the
+** table being dropped was already the last one in the database) then a
+** zero is stored in register P2. If AUTOVACUUM is disabled then a zero
+** is stored in register P2.
+**
+** This opcode throws an error if there are any active reader VMs when
+** it is invoked. This is done to avoid the difficulty associated with
+** updating existing cursors when a root page is moved in an AUTOVACUUM
+** database. This error is thrown even if the database is not an AUTOVACUUM
+** db in order to avoid introducing an incompatibility between autovacuum
+** and non-autovacuum modes.
**
** See also: Clear
*/
@@ -82702,55 +85509,45 @@ case OP_ResetSorter: {
break;
}
-/* Opcode: CreateTable P1 P2 * * *
-** Synopsis: r[P2]=root iDb=P1
-**
-** Allocate a new table in the main database file if P1==0 or in the
-** auxiliary database file if P1==1 or in an attached database if
-** P1>1. Write the root page number of the new table into
-** register P2
-**
-** The difference between a table and an index is this: A table must
-** have a 4-byte integer key and can have arbitrary data. An index
-** has an arbitrary key but no data.
-**
-** See also: CreateIndex
-*/
-/* Opcode: CreateIndex P1 P2 * * *
-** Synopsis: r[P2]=root iDb=P1
-**
-** Allocate a new index in the main database file if P1==0 or in the
-** auxiliary database file if P1==1 or in an attached database if
-** P1>1. Write the root page number of the new table into
-** register P2.
+/* Opcode: CreateBtree P1 P2 P3 * *
+** Synopsis: r[P2]=root iDb=P1 flags=P3
**
-** See documentation on OP_CreateTable for additional information.
+** Allocate a new b-tree in the main database file if P1==0 or in the
+** TEMP database file if P1==1 or in an attached database if
+** P1>1. The P3 argument must be 1 (BTREE_INTKEY) for a rowid table
+** it must be 2 (BTREE_BLOBKEY) for a index or WITHOUT ROWID table.
+** The root page number of the new b-tree is stored in register P2.
*/
-case OP_CreateIndex: /* out2 */
-case OP_CreateTable: { /* out2 */
+case OP_CreateBtree: { /* out2 */
int pgno;
- int flags;
Db *pDb;
pOut = out2Prerelease(p, pOp);
pgno = 0;
+ assert( pOp->p3==BTREE_INTKEY || pOp->p3==BTREE_BLOBKEY );
assert( pOp->p1>=0 && pOp->p1nDb );
assert( DbMaskTest(p->btreeMask, pOp->p1) );
assert( p->readOnly==0 );
pDb = &db->aDb[pOp->p1];
assert( pDb->pBt!=0 );
- if( pOp->opcode==OP_CreateTable ){
- /* flags = BTREE_INTKEY; */
- flags = BTREE_INTKEY;
- }else{
- flags = BTREE_BLOBKEY;
- }
- rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, flags);
+ rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, pOp->p3);
if( rc ) goto abort_due_to_error;
pOut->u.i = pgno;
break;
}
+/* Opcode: SqlExec * * * P4 *
+**
+** Run the SQL statement or statements specified in the P4 string.
+*/
+case OP_SqlExec: {
+ db->nSqlExec++;
+ rc = sqlite3_exec(db, pOp->p4.z, 0, 0, 0);
+ db->nSqlExec--;
+ if( rc ) goto abort_due_to_error;
+ break;
+}
+
/* Opcode: ParseSchema P1 * * P4 *
**
** Read and parse all entries from the SQLITE_MASTER table of database P1
@@ -82779,7 +85576,7 @@ case OP_ParseSchema: {
assert( iDb>=0 && iDbnDb );
assert( DbHasProperty(db, iDb, DB_SchemaLoaded) );
/* Used to be a conditional */ {
- zMaster = SCHEMA_TABLE(iDb);
+ zMaster = MASTER_NAME;
initData.db = db;
initData.iDb = pOp->p1;
initData.pzErrMsg = &p->zErrMsg;
@@ -82795,7 +85592,7 @@ case OP_ParseSchema: {
assert( !db->mallocFailed );
rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
if( rc==SQLITE_OK ) rc = initData.rc;
- sqlite3DbFree(db, zSql);
+ sqlite3DbFreeNN(db, zSql);
db->init.busy = 0;
}
}
@@ -82871,7 +85668,7 @@ case OP_DropTrigger: {
** register P1 the text of an error message describing any problems.
** If no problems are found, store a NULL in register P1.
**
-** The register P3 contains the maximum number of allowed errors.
+** The register P3 contains one less than the maximum number of allowed errors.
** At most reg(P3) errors will be reported.
** In other words, the analysis stops as soon as reg(P1) errors are
** seen. Reg(P1) is updated with the number of errors remaining.
@@ -82895,7 +85692,7 @@ case OP_IntegrityCk: {
nRoot = pOp->p2;
aRoot = pOp->p4.ai;
assert( nRoot>0 );
- assert( aRoot[nRoot]==0 );
+ assert( aRoot[0]==nRoot );
assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
pnErr = &aMem[pOp->p3];
assert( (pnErr->flags & MEM_Int)!=0 );
@@ -82903,15 +85700,15 @@ case OP_IntegrityCk: {
pIn1 = &aMem[pOp->p1];
assert( pOp->p5nDb );
assert( DbMaskTest(p->btreeMask, pOp->p5) );
- z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, aRoot, nRoot,
- (int)pnErr->u.i, &nErr);
- pnErr->u.i -= nErr;
+ z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, &aRoot[1], nRoot,
+ (int)pnErr->u.i+1, &nErr);
sqlite3VdbeMemSetNull(pIn1);
if( nErr==0 ){
assert( z==0 );
}else if( z==0 ){
goto no_mem;
}else{
+ pnErr->u.i -= nErr-1;
sqlite3VdbeMemSetStr(pIn1, z, -1, SQLITE_UTF8, sqlite3_free);
}
UPDATE_MAX_BLOBSIZE(pIn1);
@@ -82923,7 +85720,7 @@ case OP_IntegrityCk: {
/* Opcode: RowSetAdd P1 P2 * * *
** Synopsis: rowset(P1)=r[P2]
**
-** Insert the integer value held by register P2 into a boolean index
+** Insert the integer value held by register P2 into a RowSet object
** held in register P1.
**
** An assertion fails if P2 is not an integer.
@@ -82943,8 +85740,9 @@ case OP_RowSetAdd: { /* in1, in2 */
/* Opcode: RowSetRead P1 P2 P3 * *
** Synopsis: r[P3]=rowset(P1)
**
-** Extract the smallest value from boolean index P1 and put that value into
-** register P3. Or, if boolean index P1 is initially empty, leave P3
+** Extract the smallest value from the RowSet object in P1
+** and put that value into register P3.
+** Or, if RowSet object P1 is initially empty, leave P3
** unchanged and jump to instruction P2.
*/
case OP_RowSetRead: { /* jump, in1, out3 */
@@ -82975,15 +85773,14 @@ case OP_RowSetRead: { /* jump, in1, out3 */
** integer in P3 into the RowSet and continue on to the
** next opcode.
**
-** The RowSet object is optimized for the case where successive sets
-** of integers, where each set contains no duplicates. Each set
-** of values is identified by a unique P4 value. The first set
-** must have P4==0, the final set P4=-1. P4 must be either -1 or
-** non-negative. For non-negative values of P4 only the lower 4
-** bits are significant.
+** The RowSet object is optimized for the case where sets of integers
+** are inserted in distinct phases, which each set contains no duplicates.
+** Each set is identified by a unique P4 value. The first set
+** must have P4==0, the final set must have P4==-1, and for all other sets
+** must have P4>0.
**
** This allows optimizations: (a) when P4==0 there is no need to test
-** the rowset object for P3, as it is guaranteed not to contain it,
+** the RowSet object for P3, as it is guaranteed not to contain it,
** (b) when P4==-1 there is no need to insert the value, as it will
** never be tested for, and (c) when a value that is part of set X is
** inserted, there is no need to search to see if the same value was
@@ -83090,7 +85887,8 @@ case OP_Program: { /* jump */
if( pProgram->nCsr==0 ) nMem++;
nByte = ROUND8(sizeof(VdbeFrame))
+ nMem * sizeof(Mem)
- + pProgram->nCsr * sizeof(VdbeCursor *);
+ + pProgram->nCsr * sizeof(VdbeCursor*)
+ + (pProgram->nOp + 7)/8;
pFrame = sqlite3DbMallocZero(db, nByte);
if( !pFrame ){
goto no_mem;
@@ -83129,7 +85927,7 @@ case OP_Program: { /* jump */
p->nFrame++;
pFrame->pParent = p->pFrame;
- pFrame->lastRowid = lastRowid;
+ pFrame->lastRowid = db->lastRowid;
pFrame->nChange = p->nChange;
pFrame->nDbChange = p->db->nChange;
assert( pFrame->pAuxData==0 );
@@ -83141,6 +85939,8 @@ case OP_Program: { /* jump */
p->nMem = pFrame->nChildMem;
p->nCursor = (u16)pFrame->nChildCsr;
p->apCsr = (VdbeCursor **)&aMem[p->nMem];
+ pFrame->aOnce = (u8*)&p->apCsr[pProgram->nCsr];
+ memset(pFrame->aOnce, 0, (pProgram->nOp + 7)/8);
p->aOp = aOp = pProgram->aOp;
p->nOp = pProgram->nOp;
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
@@ -83290,29 +86090,42 @@ case OP_IfPos: { /* jump, in1 */
** Otherwise, r[P2] is set to the sum of r[P1] and r[P3].
*/
case OP_OffsetLimit: { /* in1, out2, in3 */
+ i64 x;
pIn1 = &aMem[pOp->p1];
pIn3 = &aMem[pOp->p3];
pOut = out2Prerelease(p, pOp);
assert( pIn1->flags & MEM_Int );
assert( pIn3->flags & MEM_Int );
- pOut->u.i = pIn1->u.i<=0 ? -1 : pIn1->u.i+(pIn3->u.i>0?pIn3->u.i:0);
+ x = pIn1->u.i;
+ if( x<=0 || sqlite3AddInt64(&x, pIn3->u.i>0?pIn3->u.i:0) ){
+ /* If the LIMIT is less than or equal to zero, loop forever. This
+ ** is documented. But also, if the LIMIT+OFFSET exceeds 2^63 then
+ ** also loop forever. This is undocumented. In fact, one could argue
+ ** that the loop should terminate. But assuming 1 billion iterations
+ ** per second (far exceeding the capabilities of any current hardware)
+ ** it would take nearly 300 years to actually reach the limit. So
+ ** looping forever is a reasonable approximation. */
+ pOut->u.i = -1;
+ }else{
+ pOut->u.i = x;
+ }
break;
}
-/* Opcode: IfNotZero P1 P2 P3 * *
-** Synopsis: if r[P1]!=0 then r[P1]-=P3, goto P2
+/* Opcode: IfNotZero P1 P2 * * *
+** Synopsis: if r[P1]!=0 then r[P1]--, goto P2
**
** Register P1 must contain an integer. If the content of register P1 is
-** initially nonzero, then subtract P3 from the value in register P1 and
-** jump to P2. If register P1 is initially zero, leave it unchanged
-** and fall through.
+** initially greater than zero, then decrement the value in register P1.
+** If it is non-zero (negative or positive) and then also jump to P2.
+** If register P1 is initially zero, leave it unchanged and fall through.
*/
case OP_IfNotZero: { /* jump, in1 */
pIn1 = &aMem[pOp->p1];
assert( pIn1->flags&MEM_Int );
VdbeBranchTaken(pIn1->u.i<0, 2);
if( pIn1->u.i ){
- pIn1->u.i -= pOp->p3;
+ if( pIn1->u.i>0 ) pIn1->u.i--;
goto jump_to_p2;
}
break;
@@ -83321,13 +86134,13 @@ case OP_IfNotZero: { /* jump, in1 */
/* Opcode: DecrJumpZero P1 P2 * * *
** Synopsis: if (--r[P1])==0 goto P2
**
-** Register P1 must hold an integer. Decrement the value in register P1
-** then jump to P2 if the new value is exactly zero.
+** Register P1 must hold an integer. Decrement the value in P1
+** and jump to P2 if the new value is exactly zero.
*/
case OP_DecrJumpZero: { /* jump, in1 */
pIn1 = &aMem[pOp->p1];
assert( pIn1->flags&MEM_Int );
- pIn1->u.i--;
+ if( pIn1->u.i>SMALLEST_INT64 ) pIn1->u.i--;
VdbeBranchTaken(pIn1->u.i==0, 2);
if( pIn1->u.i==0 ) goto jump_to_p2;
break;
@@ -83573,7 +86386,7 @@ case OP_JournalMode: { /* out2 */
** file. An EXCLUSIVE lock may still be held on the database file
** after a successful return.
*/
- rc = sqlite3PagerCloseWal(pPager);
+ rc = sqlite3PagerCloseWal(pPager, db);
if( rc==SQLITE_OK ){
sqlite3PagerSetJournalMode(pPager, eNew);
}
@@ -83683,7 +86496,7 @@ case OP_Expire: {
*/
case OP_TableLock: {
u8 isWriteLock = (u8)pOp->p3;
- if( isWriteLock || 0==(db->flags&SQLITE_ReadUncommitted) ){
+ if( isWriteLock || 0==(db->flags&SQLITE_ReadUncommit) ){
int p1 = pOp->p1;
assert( p1>=0 && p1nDb );
assert( DbMaskTest(p->btreeMask, p1) );
@@ -83874,12 +86687,18 @@ case OP_VFilter: { /* jump */
#endif /* SQLITE_OMIT_VIRTUALTABLE */
#ifndef SQLITE_OMIT_VIRTUALTABLE
-/* Opcode: VColumn P1 P2 P3 * *
+/* Opcode: VColumn P1 P2 P3 * P5
** Synopsis: r[P3]=vcolumn(P2)
**
-** Store the value of the P2-th column of
-** the row of the virtual-table that the
-** P1 cursor is pointing to into register P3.
+** Store in register P3 the value of the P2-th column of
+** the current row of the virtual-table of cursor P1.
+**
+** If the VColumn opcode is being used to fetch the value of
+** an unchanging column during an UPDATE operation, then the P5
+** value is 1. Otherwise, P5 is 0. The P5 value is returned
+** by sqlite3_vtab_nochange() routine can can be used
+** by virtual table implementations to return special "no-change"
+** marks which can be more efficient, depending on the virtual table.
*/
case OP_VColumn: {
sqlite3_vtab *pVtab;
@@ -83901,7 +86720,13 @@ case OP_VColumn: {
assert( pModule->xColumn );
memset(&sContext, 0, sizeof(sContext));
sContext.pOut = pDest;
- MemSetTypeFlag(pDest, MEM_Null);
+ if( pOp->p5 ){
+ sqlite3VdbeMemSetNull(pDest);
+ pDest->flags = MEM_Null|MEM_Zero;
+ pDest->u.nZero = 0;
+ }else{
+ MemSetTypeFlag(pDest, MEM_Null);
+ }
rc = pModule->xColumn(pCur->uc.pVCur, &sContext, pOp->p2);
sqlite3VtabImportErrmsg(p, pVtab);
if( sContext.isError ){
@@ -84057,7 +86882,7 @@ case OP_VUpdate: {
sqlite3VtabImportErrmsg(p, pVtab);
if( rc==SQLITE_OK && pOp->p1 ){
assert( nArg>1 && apArg[0] && (apArg[0]->flags&MEM_Null) );
- db->lastRowid = lastRowid = rowid;
+ db->lastRowid = rowid;
}
if( (rc&0xff)==SQLITE_CONSTRAINT && pOp->p4.pVtab->bConstraint ){
if( pOp->p5==OE_Ignore ){
@@ -84112,8 +86937,129 @@ case OP_MaxPgcnt: { /* out2 */
}
#endif
+/* Opcode: Function0 P1 P2 P3 P4 P5
+** Synopsis: r[P3]=func(r[P2@P5])
+**
+** Invoke a user function (P4 is a pointer to a FuncDef object 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
+** whether meta data associated with a user function argument using the
+** sqlite3_set_auxdata() API may be safely retained until the next
+** invocation of this opcode.
+**
+** See also: Function, AggStep, AggFinal
+*/
+/* Opcode: Function P1 P2 P3 P4 P5
+** Synopsis: r[P3]=func(r[P2@P5])
+**
+** Invoke a user function (P4 is a pointer to an sqlite3_context object that
+** contains a pointer to the function to be run) 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
+** whether meta data associated with a user function argument using the
+** sqlite3_set_auxdata() API may be safely retained until the next
+** invocation of this opcode.
+**
+** SQL functions are initially coded as OP_Function0 with P4 pointing
+** to a FuncDef object. But on first evaluation, the P4 operand is
+** automatically converted into an sqlite3_context object and the operation
+** changed to this OP_Function opcode. In this way, the initialization of
+** the sqlite3_context object occurs only once, rather than once for each
+** evaluation of the function.
+**
+** See also: Function0, AggStep, AggFinal
+*/
+case OP_PureFunc0:
+case OP_Function0: {
+ int n;
+ sqlite3_context *pCtx;
+
+ assert( pOp->p4type==P4_FUNCDEF );
+ n = pOp->p5;
+ assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
+ assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem+1 - p->nCursor)+1) );
+ assert( pOp->p3p2 || pOp->p3>=pOp->p2+n );
+ pCtx = sqlite3DbMallocRawNN(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*));
+ if( pCtx==0 ) goto no_mem;
+ pCtx->pOut = 0;
+ pCtx->pFunc = pOp->p4.pFunc;
+ pCtx->iOp = (int)(pOp - aOp);
+ pCtx->pVdbe = p;
+ pCtx->argc = n;
+ pOp->p4type = P4_FUNCCTX;
+ pOp->p4.pCtx = pCtx;
+ assert( OP_PureFunc == OP_PureFunc0+2 );
+ assert( OP_Function == OP_Function0+2 );
+ pOp->opcode += 2;
+ /* Fall through into OP_Function */
+}
+case OP_PureFunc:
+case OP_Function: {
+ int i;
+ sqlite3_context *pCtx;
+
+ assert( pOp->p4type==P4_FUNCCTX );
+ pCtx = pOp->p4.pCtx;
+
+ /* If this function is inside of a trigger, the register array in aMem[]
+ ** might change from one evaluation to the next. The next block of code
+ ** checks to see if the register array has changed, and if so it
+ ** reinitializes the relavant parts of the sqlite3_context object */
+ pOut = &aMem[pOp->p3];
+ if( pCtx->pOut != pOut ){
+ pCtx->pOut = pOut;
+ for(i=pCtx->argc-1; i>=0; i--) pCtx->argv[i] = &aMem[pOp->p2+i];
+ }
+
+ memAboutToChange(p, pOut);
+#ifdef SQLITE_DEBUG
+ for(i=0; iargc; i++){
+ assert( memIsValid(pCtx->argv[i]) );
+ REGISTER_TRACE(pOp->p2+i, pCtx->argv[i]);
+ }
+#endif
+ MemSetTypeFlag(pOut, MEM_Null);
+ pCtx->fErrorOrAux = 0;
+ (*pCtx->pFunc->xSFunc)(pCtx, pCtx->argc, pCtx->argv);/* IMP: R-24505-23230 */
-/* Opcode: Init P1 P2 * P4 *
+ /* If the function returned an error, throw an exception */
+ if( pCtx->fErrorOrAux ){
+ if( pCtx->isError ){
+ sqlite3VdbeError(p, "%s", sqlite3_value_text(pOut));
+ rc = pCtx->isError;
+ }
+ sqlite3VdbeDeleteAuxData(db, &p->pAuxData, pCtx->iOp, pOp->p1);
+ if( rc ) goto abort_due_to_error;
+ }
+
+ /* Copy the result of the function into register P3 */
+ if( pOut->flags & (MEM_Str|MEM_Blob) ){
+ sqlite3VdbeChangeEncoding(pOut, encoding);
+ if( sqlite3VdbeMemTooBig(pOut) ) goto too_big;
+ }
+
+ REGISTER_TRACE(pOp->p3, pOut);
+ UPDATE_MAX_BLOBSIZE(pOut);
+ break;
+}
+
+/* Opcode: Trace P1 P2 * P4 *
+**
+** Write P4 on the statement trace output if statement tracing is
+** enabled.
+**
+** Operand P1 must be 0x7fffffff and P2 must positive.
+*/
+/* Opcode: Init P1 P2 P3 P4 *
** Synopsis: Start at P2
**
** Programs contain a single instance of this opcode as the very first
@@ -84127,7 +87073,11 @@ case OP_MaxPgcnt: { /* out2 */
**
** Increment the value of P1 so that OP_Once opcodes will jump the
** first time they are evaluated for this run.
+**
+** If P3 is not zero, then it is an address to jump to if an SQLITE_CORRUPT
+** error is encountered.
*/
+case OP_Trace:
case OP_Init: { /* jump */
char *zTrace;
int i;
@@ -84142,7 +87092,9 @@ case OP_Init: { /* jump */
** sqlite3_expanded_sql(P) otherwise.
*/
assert( pOp->p4.z==0 || strncmp(pOp->p4.z, "-" "- ", 3)==0 );
- assert( pOp==p->aOp ); /* Always instruction 0 */
+
+ /* OP_Init is always instruction 0 */
+ assert( pOp==p->aOp || pOp->opcode==OP_Trace );
#ifndef SQLITE_OMIT_TRACE
if( (db->mTrace & (SQLITE_TRACE_STMT|SQLITE_TRACE_LEGACY))!=0
@@ -84157,7 +87109,11 @@ case OP_Init: { /* jump */
sqlite3_free(z);
}else
#endif
- {
+ if( db->nVdbeExec>1 ){
+ char *z = sqlite3MPrintf(db, "-- %s", zTrace);
+ (void)db->xTrace(SQLITE_TRACE_STMT, db->pTraceArg, p, z);
+ sqlite3DbFree(db, z);
+ }else{
(void)db->xTrace(SQLITE_TRACE_STMT, db->pTraceArg, p, zTrace);
}
}
@@ -84181,12 +87137,14 @@ case OP_Init: { /* jump */
#endif /* SQLITE_OMIT_TRACE */
assert( pOp->p2>0 );
if( pOp->p1>=sqlite3GlobalConfig.iOnceResetThreshold ){
+ if( pOp->opcode==OP_Trace ) break;
for(i=1; inOp; i++){
if( p->aOp[i].opcode==OP_Once ) p->aOp[i].p1 = 0;
}
pOp->p1 = 0;
}
pOp->p1++;
+ p->aCounter[SQLITE_STMTSTATUS_RUN]++;
goto jump_to_p2;
}
@@ -84293,7 +87251,6 @@ default: { /* This is really OP_Noop and OP_Explain */
** release the mutexes on btrees that were acquired at the
** top. */
vdbe_return:
- db->lastRowid = lastRowid;
testcase( nVmStep>0 );
p->aCounter[SQLITE_STMTSTATUS_VM_STEP] += (int)nVmStep;
sqlite3VdbeLeave(p);
@@ -84357,10 +87314,9 @@ default: { /* This is really OP_Noop and OP_Explain */
*/
typedef struct Incrblob Incrblob;
struct Incrblob {
- int flags; /* Copy of "flags" passed to sqlite3_blob_open() */
int nByte; /* Size of open blob, in bytes */
int iOffset; /* Byte offset of blob in cursor data */
- int iCol; /* Table column this handle is open on */
+ u16 iCol; /* Table column this handle is open on */
BtCursor *pCsr; /* Cursor pointing at blob row */
sqlite3_stmt *pStmt; /* Statement holding cursor open */
sqlite3 *db; /* The associated database */
@@ -84391,17 +87347,28 @@ static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){
char *zErr = 0; /* Error message */
Vdbe *v = (Vdbe *)p->pStmt;
- /* Set the value of the SQL statements only variable to integer iRow.
- ** This is done directly instead of using sqlite3_bind_int64() to avoid
- ** triggering asserts related to mutexes.
+ /* Set the value of register r[1] in the SQL statement to integer iRow.
+ ** This is done directly as a performance optimization
*/
- assert( v->aVar[0].flags&MEM_Int );
- v->aVar[0].u.i = iRow;
+ v->aMem[1].flags = MEM_Int;
+ v->aMem[1].u.i = iRow;
- rc = sqlite3_step(p->pStmt);
+ /* If the statement has been run before (and is paused at the OP_ResultRow)
+ ** then back it up to the point where it does the OP_NotExists. This could
+ ** have been down with an extra OP_Goto, but simply setting the program
+ ** counter is faster. */
+ if( v->pc>4 ){
+ v->pc = 4;
+ assert( v->aOp[v->pc].opcode==OP_NotExists );
+ rc = sqlite3VdbeExec(v);
+ }else{
+ rc = sqlite3_step(p->pStmt);
+ }
if( rc==SQLITE_ROW ){
VdbeCursor *pC = v->apCsr[0];
- u32 type = pC->aType[p->iCol];
+ u32 type = pC->nHdrParsed>p->iCol ? pC->aType[p->iCol] : 0;
+ testcase( pC->nHdrParsed==p->iCol );
+ testcase( pC->nHdrParsed==p->iCol+1 );
if( type<12 ){
zErr = sqlite3MPrintf(p->db, "cannot open value of type %s",
type==0?"null": type==7?"real": "integer"
@@ -84446,7 +87413,7 @@ SQLITE_API int sqlite3_blob_open(
const char *zTable, /* The table containing the blob */
const char *zColumn, /* The column containing the blob */
sqlite_int64 iRow, /* The row containing the glob */
- int flags, /* True -> read/write access, false -> read-only */
+ int wrFlag, /* True -> read/write access, false -> read-only */
sqlite3_blob **ppBlob /* Handle for accessing the blob returned here */
){
int nAttempt = 0;
@@ -84454,8 +87421,8 @@ SQLITE_API int sqlite3_blob_open(
int rc = SQLITE_OK;
char *zErr = 0;
Table *pTab;
- Parse *pParse = 0;
Incrblob *pBlob = 0;
+ Parse sParse;
#ifdef SQLITE_ENABLE_API_ARMOR
if( ppBlob==0 ){
@@ -84468,42 +87435,39 @@ SQLITE_API int sqlite3_blob_open(
return SQLITE_MISUSE_BKPT;
}
#endif
- flags = !!flags; /* flags = (flags ? 1 : 0); */
+ wrFlag = !!wrFlag; /* wrFlag = (wrFlag ? 1 : 0); */
sqlite3_mutex_enter(db->mutex);
pBlob = (Incrblob *)sqlite3DbMallocZero(db, sizeof(Incrblob));
- if( !pBlob ) goto blob_open_out;
- pParse = sqlite3StackAllocRaw(db, sizeof(*pParse));
- if( !pParse ) goto blob_open_out;
-
do {
- memset(pParse, 0, sizeof(Parse));
- pParse->db = db;
+ memset(&sParse, 0, sizeof(Parse));
+ if( !pBlob ) goto blob_open_out;
+ sParse.db = db;
sqlite3DbFree(db, zErr);
zErr = 0;
sqlite3BtreeEnterAll(db);
- pTab = sqlite3LocateTable(pParse, 0, zTable, zDb);
+ pTab = sqlite3LocateTable(&sParse, 0, zTable, zDb);
if( pTab && IsVirtual(pTab) ){
pTab = 0;
- sqlite3ErrorMsg(pParse, "cannot open virtual table: %s", zTable);
+ sqlite3ErrorMsg(&sParse, "cannot open virtual table: %s", zTable);
}
if( pTab && !HasRowid(pTab) ){
pTab = 0;
- sqlite3ErrorMsg(pParse, "cannot open table without rowid: %s", zTable);
+ sqlite3ErrorMsg(&sParse, "cannot open table without rowid: %s", zTable);
}
#ifndef SQLITE_OMIT_VIEW
if( pTab && pTab->pSelect ){
pTab = 0;
- sqlite3ErrorMsg(pParse, "cannot open view: %s", zTable);
+ sqlite3ErrorMsg(&sParse, "cannot open view: %s", zTable);
}
#endif
if( !pTab ){
- if( pParse->zErrMsg ){
+ if( sParse.zErrMsg ){
sqlite3DbFree(db, zErr);
- zErr = pParse->zErrMsg;
- pParse->zErrMsg = 0;
+ zErr = sParse.zErrMsg;
+ sParse.zErrMsg = 0;
}
rc = SQLITE_ERROR;
sqlite3BtreeLeaveAll(db);
@@ -84528,9 +87492,8 @@ SQLITE_API int sqlite3_blob_open(
/* If the value is being opened for writing, check that the
** column is not indexed, and that it is not part of a foreign key.
- ** It is against the rules to open a column to which either of these
- ** descriptions applies for writing. */
- if( flags ){
+ */
+ if( wrFlag ){
const char *zFault = 0;
Index *pIdx;
#ifndef SQLITE_OMIT_FOREIGN_KEY
@@ -84568,7 +87531,7 @@ SQLITE_API int sqlite3_blob_open(
}
}
- pBlob->pStmt = (sqlite3_stmt *)sqlite3VdbeCreate(pParse);
+ pBlob->pStmt = (sqlite3_stmt *)sqlite3VdbeCreate(&sParse);
assert( pBlob->pStmt || db->mallocFailed );
if( pBlob->pStmt ){
@@ -84591,22 +87554,21 @@ SQLITE_API int sqlite3_blob_open(
static const VdbeOpList openBlob[] = {
{OP_TableLock, 0, 0, 0}, /* 0: Acquire a read or write lock */
{OP_OpenRead, 0, 0, 0}, /* 1: Open a cursor */
- {OP_Variable, 1, 1, 0}, /* 2: Move ?1 into reg[1] */
- {OP_NotExists, 0, 7, 1}, /* 3: Seek the cursor */
- {OP_Column, 0, 0, 1}, /* 4 */
- {OP_ResultRow, 1, 0, 0}, /* 5 */
- {OP_Goto, 0, 2, 0}, /* 6 */
- {OP_Close, 0, 0, 0}, /* 7 */
- {OP_Halt, 0, 0, 0}, /* 8 */
+ /* blobSeekToRow() will initialize r[1] to the desired rowid */
+ {OP_NotExists, 0, 5, 1}, /* 2: Seek the cursor to rowid=r[1] */
+ {OP_Column, 0, 0, 1}, /* 3 */
+ {OP_ResultRow, 1, 0, 0}, /* 4 */
+ {OP_Halt, 0, 0, 0}, /* 5 */
};
Vdbe *v = (Vdbe *)pBlob->pStmt;
int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
VdbeOp *aOp;
- sqlite3VdbeAddOp4Int(v, OP_Transaction, iDb, flags,
+ sqlite3VdbeAddOp4Int(v, OP_Transaction, iDb, wrFlag,
pTab->pSchema->schema_cookie,
pTab->pSchema->iGeneration);
- sqlite3VdbeChangeP5(v, 1);
+ sqlite3VdbeChangeP5(v, 1);
+ assert( sqlite3VdbeCurrentAddr(v)==2 || db->mallocFailed );
aOp = sqlite3VdbeAddOpList(v, ArraySize(openBlob), openBlob, iLn);
/* Make sure a mutex is held on the table to be accessed */
@@ -84620,15 +87582,15 @@ SQLITE_API int sqlite3_blob_open(
#else
aOp[0].p1 = iDb;
aOp[0].p2 = pTab->tnum;
- aOp[0].p3 = flags;
- sqlite3VdbeChangeP4(v, 1, pTab->zName, P4_TRANSIENT);
+ aOp[0].p3 = wrFlag;
+ sqlite3VdbeChangeP4(v, 2, pTab->zName, P4_TRANSIENT);
}
if( db->mallocFailed==0 ){
#endif
/* Remove either the OP_OpenWrite or OpenRead. Set the P2
** parameter of the other to pTab->tnum. */
- if( flags ) aOp[1].opcode = OP_OpenWrite;
+ if( wrFlag ) aOp[1].opcode = OP_OpenWrite;
aOp[1].p2 = pTab->tnum;
aOp[1].p3 = iDb;
@@ -84641,23 +87603,21 @@ SQLITE_API int sqlite3_blob_open(
*/
aOp[1].p4type = P4_INT32;
aOp[1].p4.i = pTab->nCol+1;
- aOp[4].p2 = pTab->nCol;
+ aOp[3].p2 = pTab->nCol;
- pParse->nVar = 1;
- pParse->nMem = 1;
- pParse->nTab = 1;
- sqlite3VdbeMakeReady(v, pParse);
+ sParse.nVar = 0;
+ sParse.nMem = 1;
+ sParse.nTab = 1;
+ sqlite3VdbeMakeReady(v, &sParse);
}
}
- pBlob->flags = flags;
pBlob->iCol = iCol;
pBlob->db = db;
sqlite3BtreeLeaveAll(db);
if( db->mallocFailed ){
goto blob_open_out;
}
- sqlite3_bind_int64(pBlob->pStmt, 1, iRow);
rc = blobSeekToRow(pBlob, iRow, &zErr);
} while( (++nAttempt)mutex);
return rc;
@@ -84775,7 +87734,7 @@ static int blobReadWrite(
** Read data from a blob handle.
*/
SQLITE_API int sqlite3_blob_read(sqlite3_blob *pBlob, void *z, int n, int iOffset){
- return blobReadWrite(pBlob, z, n, iOffset, sqlite3BtreeData);
+ return blobReadWrite(pBlob, z, n, iOffset, sqlite3BtreePayloadChecked);
}
/*
@@ -85657,15 +88616,15 @@ static int vdbeSorterCompareText(
int n2;
int res;
- getVarint32(&p1[1], n1); n1 = (n1 - 13) / 2;
- getVarint32(&p2[1], n2); n2 = (n2 - 13) / 2;
- res = memcmp(v1, v2, MIN(n1, n2));
+ getVarint32(&p1[1], n1);
+ getVarint32(&p2[1], n2);
+ res = memcmp(v1, v2, (MIN(n1, n2) - 13)/2);
if( res==0 ){
res = n1 - n2;
}
if( res==0 ){
- if( pTask->pSorter->pKeyInfo->nField>1 ){
+ if( pTask->pSorter->pKeyInfo->nKeyField>1 ){
res = vdbeSorterCompareTail(
pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2
);
@@ -85700,42 +88659,41 @@ static int vdbeSorterCompareInt(
assert( (s1>0 && s1<7) || s1==8 || s1==9 );
assert( (s2>0 && s2<7) || s2==8 || s2==9 );
- if( s1>7 && s2>7 ){
- res = s1 - s2;
- }else{
- if( s1==s2 ){
- if( (*v1 ^ *v2) & 0x80 ){
- /* The two values have different signs */
- res = (*v1 & 0x80) ? -1 : +1;
- }else{
- /* The two values have the same sign. Compare using memcmp(). */
- static const u8 aLen[] = {0, 1, 2, 3, 4, 6, 8 };
- int i;
- res = 0;
- for(i=0; i7 && s2>7 ){
+ res = s1 - s2;
+ }else{
+ if( s2>7 ){
+ res = +1;
+ }else if( s1>7 ){
+ res = -1;
}else{
- if( s2>7 ){
- res = +1;
- }else if( s1>7 ){
- res = -1;
- }else{
- res = s1 - s2;
- }
- assert( res!=0 );
+ res = s1 - s2;
+ }
+ assert( res!=0 );
- if( res>0 ){
- if( *v1 & 0x80 ) res = -1;
- }else{
- if( *v2 & 0x80 ) res = +1;
- }
+ if( res>0 ){
+ if( *v1 & 0x80 ) res = -1;
+ }else{
+ if( *v2 & 0x80 ) res = +1;
}
}
if( res==0 ){
- if( pTask->pSorter->pKeyInfo->nField>1 ){
+ if( pTask->pSorter->pKeyInfo->nKeyField>1 ){
res = vdbeSorterCompareTail(
pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2
);
@@ -85750,7 +88708,7 @@ static int vdbeSorterCompareInt(
/*
** Initialize the temporary index cursor just opened as a sorter cursor.
**
-** Usually, the sorter module uses the value of (pCsr->pKeyInfo->nField)
+** Usually, the sorter module uses the value of (pCsr->pKeyInfo->nKeyField)
** to determine the number of fields that should be compared from the
** records being sorted. However, if the value passed as argument nField
** is non-zero and the sorter is able to guarantee a stable sort, nField
@@ -85801,9 +88759,9 @@ SQLITE_PRIVATE int sqlite3VdbeSorterInit(
}
#endif
- assert( pCsr->pKeyInfo && pCsr->pBt==0 );
+ assert( pCsr->pKeyInfo && pCsr->pBtx==0 );
assert( pCsr->eCurType==CURTYPE_SORTER );
- szKeyInfo = sizeof(KeyInfo) + (pCsr->pKeyInfo->nField-1)*sizeof(CollSeq*);
+ szKeyInfo = sizeof(KeyInfo) + (pCsr->pKeyInfo->nKeyField-1)*sizeof(CollSeq*);
sz = sizeof(VdbeSorter) + nWorker * sizeof(SortSubtask);
pSorter = (VdbeSorter*)sqlite3DbMallocZero(db, sz + szKeyInfo);
@@ -85815,8 +88773,7 @@ SQLITE_PRIVATE int sqlite3VdbeSorterInit(
memcpy(pKeyInfo, pCsr->pKeyInfo, szKeyInfo);
pKeyInfo->db = 0;
if( nField && nWorker==0 ){
- pKeyInfo->nXField += (pKeyInfo->nField - nField);
- pKeyInfo->nField = nField;
+ pKeyInfo->nKeyField = nField;
}
pSorter->pgsz = pgsz = sqlite3BtreeGetPageSize(db->aDb[0].pBt);
pSorter->nTask = nWorker + 1;
@@ -85844,11 +88801,9 @@ SQLITE_PRIVATE int sqlite3VdbeSorterInit(
mxCache = MIN(mxCache, SQLITE_MAX_PMASZ);
pSorter->mxPmaSize = MAX(pSorter->mnPmaSize, (int)mxCache);
- /* EVIDENCE-OF: R-26747-61719 When the application provides any amount of
- ** scratch memory using SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary
- ** large heap allocations.
- */
- if( sqlite3GlobalConfig.pScratch==0 ){
+ /* Avoid large memory allocations if the application has requested
+ ** SQLITE_CONFIG_SMALL_MALLOC. */
+ if( sqlite3GlobalConfig.bSmallMalloc==0 ){
assert( pSorter->iMemory==0 );
pSorter->nMemory = pgsz;
pSorter->list.aMemory = (u8*)sqlite3Malloc(pgsz);
@@ -85856,7 +88811,7 @@ SQLITE_PRIVATE int sqlite3VdbeSorterInit(
}
}
- if( (pKeyInfo->nField+pKeyInfo->nXField)<13
+ if( pKeyInfo->nAllField<13
&& (pKeyInfo->aColl[0]==0 || pKeyInfo->aColl[0]==db->pDfltColl)
){
pSorter->typeMask = SORTER_TYPE_INTEGER | SORTER_TYPE_TEXT;
@@ -86169,13 +89124,9 @@ static int vdbeSorterOpenTempFile(
*/
static int vdbeSortAllocUnpacked(SortSubtask *pTask){
if( pTask->pUnpacked==0 ){
- char *pFree;
- pTask->pUnpacked = sqlite3VdbeAllocUnpackedRecord(
- pTask->pSorter->pKeyInfo, 0, 0, &pFree
- );
- assert( pTask->pUnpacked==(UnpackedRecord*)pFree );
- if( pFree==0 ) return SQLITE_NOMEM_BKPT;
- pTask->pUnpacked->nField = pTask->pSorter->pKeyInfo->nField;
+ pTask->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pTask->pSorter->pKeyInfo);
+ if( pTask->pUnpacked==0 ) return SQLITE_NOMEM_BKPT;
+ pTask->pUnpacked->nField = pTask->pSorter->pKeyInfo->nKeyField;
pTask->pUnpacked->errCode = 0;
}
return SQLITE_OK;
@@ -87459,9 +90410,13 @@ SQLITE_PRIVATE int sqlite3VdbeSorterRewind(const VdbeCursor *pCsr, int *pbEof){
}
/*
-** Advance to the next element in the sorter.
+** Advance to the next element in the sorter. Return value:
+**
+** SQLITE_OK success
+** SQLITE_DONE end of data
+** otherwise some kind of error.
*/
-SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *db, const VdbeCursor *pCsr, int *pbEof){
+SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *db, const VdbeCursor *pCsr){
VdbeSorter *pSorter;
int rc; /* Return code */
@@ -87475,21 +90430,22 @@ SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *db, const VdbeCursor *pCsr, in
#if SQLITE_MAX_WORKER_THREADS>0
if( pSorter->bUseThreads ){
rc = vdbePmaReaderNext(pSorter->pReader);
- *pbEof = (pSorter->pReader->pFd==0);
+ if( rc==SQLITE_OK && pSorter->pReader->pFd==0 ) rc = SQLITE_DONE;
}else
#endif
/*if( !pSorter->bUseThreads )*/ {
+ int res = 0;
assert( pSorter->pMerger!=0 );
assert( pSorter->pMerger->pTask==(&pSorter->aTask[0]) );
- rc = vdbeMergeEngineStep(pSorter->pMerger, pbEof);
+ rc = vdbeMergeEngineStep(pSorter->pMerger, &res);
+ if( rc==SQLITE_OK && res ) rc = SQLITE_DONE;
}
}else{
SorterRecord *pFree = pSorter->list.pList;
pSorter->list.pList = pFree->u.pNext;
pFree->u.pNext = 0;
if( pSorter->list.aMemory==0 ) vdbeSorterRecordFree(db, pFree);
- *pbEof = !pSorter->list.pList;
- rc = SQLITE_OK;
+ rc = pSorter->list.pList ? SQLITE_OK : SQLITE_DONE;
}
return rc;
}
@@ -87575,9 +90531,7 @@ SQLITE_PRIVATE int sqlite3VdbeSorterCompare(
r2 = pSorter->pUnpacked;
pKeyInfo = pCsr->pKeyInfo;
if( r2==0 ){
- char *p;
- r2 = pSorter->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pKeyInfo,0,0,&p);
- assert( pSorter->pUnpacked==(UnpackedRecord*)p );
+ r2 = pSorter->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pKeyInfo);
if( r2==0 ) return SQLITE_NOMEM_BKPT;
r2->nField = nKeyCol;
}
@@ -87696,7 +90650,8 @@ static int memjrnlRead(
int iChunkOffset;
FileChunk *pChunk;
-#ifdef SQLITE_ENABLE_ATOMIC_WRITE
+#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \
+ || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
if( (iAmt+iOfst)>p->endpoint.iOffset ){
return SQLITE_IOERR_SHORT_READ;
}
@@ -87815,7 +90770,8 @@ static int memjrnlWrite(
** atomic-write optimization. In this case the first 28 bytes of the
** journal file may be written as part of committing the transaction. */
assert( iOfst==p->endpoint.iOffset || iOfst==0 );
-#ifdef SQLITE_ENABLE_ATOMIC_WRITE
+#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \
+ || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
if( iOfst==0 && p->pFirst ){
assert( p->nChunkSize>iAmt );
memcpy((u8*)p->pFirst->zChunk, zBuf, iAmt);
@@ -87984,17 +90940,31 @@ SQLITE_PRIVATE void sqlite3MemJournalOpen(sqlite3_file *pJfd){
sqlite3JournalOpen(0, 0, pJfd, 0, -1);
}
-#ifdef SQLITE_ENABLE_ATOMIC_WRITE
+#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \
+ || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
/*
** If the argument p points to a MemJournal structure that is not an
** in-memory-only journal file (i.e. is one that was opened with a +ve
-** nSpill parameter), and the underlying file has not yet been created,
-** create it now.
+** nSpill parameter or as SQLITE_OPEN_MAIN_JOURNAL), and the underlying
+** file has not yet been created, create it now.
*/
-SQLITE_PRIVATE int sqlite3JournalCreate(sqlite3_file *p){
+SQLITE_PRIVATE int sqlite3JournalCreate(sqlite3_file *pJfd){
int rc = SQLITE_OK;
- if( p->pMethods==&MemJournalMethods && ((MemJournal*)p)->nSpill>0 ){
- rc = memjrnlCreateFile((MemJournal*)p);
+ MemJournal *p = (MemJournal*)pJfd;
+ if( p->pMethod==&MemJournalMethods && (
+#ifdef SQLITE_ENABLE_ATOMIC_WRITE
+ p->nSpill>0
+#else
+ /* While this appears to not be possible without ATOMIC_WRITE, the
+ ** paths are complex, so it seems prudent to leave the test in as
+ ** a NEVER(), in case our analysis is subtly flawed. */
+ NEVER(p->nSpill>0)
+#endif
+#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
+ || (p->flags & SQLITE_OPEN_MAIN_JOURNAL)
+#endif
+ )){
+ rc = memjrnlCreateFile(p);
}
return rc;
}
@@ -88048,11 +91018,11 @@ SQLITE_PRIVATE int sqlite3JournalSize(sqlite3_vfs *pVfs){
**
** WRC_Continue Continue descending down the tree.
**
-** WRC_Prune Do not descend into child nodes. But allow
+** WRC_Prune Do not descend into child nodes, but allow
** the walk to continue with sibling nodes.
**
** WRC_Abort Do no more callbacks. Unwind the stack and
-** return the top-level walk call.
+** return from the top-level walk call.
**
** The return value from this routine is WRC_Abort to abandon the tree walk
** and WRC_Continue to continue.
@@ -88061,16 +91031,22 @@ static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){
int rc;
testcase( ExprHasProperty(pExpr, EP_TokenOnly) );
testcase( ExprHasProperty(pExpr, EP_Reduced) );
- rc = pWalker->xExprCallback(pWalker, pExpr);
- if( rc || ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){
- return rc & WRC_Abort;
- }
- if( pExpr->pLeft && walkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort;
- if( pExpr->pRight && walkExpr(pWalker, pExpr->pRight) ) return WRC_Abort;
- if( ExprHasProperty(pExpr, EP_xIsSelect) ){
- if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort;
- }else if( pExpr->x.pList ){
- if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
+ while(1){
+ rc = pWalker->xExprCallback(pWalker, pExpr);
+ if( rc ) return rc & WRC_Abort;
+ if( !ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){
+ if( pExpr->pLeft && walkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort;
+ assert( pExpr->x.pList==0 || pExpr->pRight==0 );
+ if( pExpr->pRight ){
+ pExpr = pExpr->pRight;
+ continue;
+ }else if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+ if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort;
+ }else if( pExpr->x.pList ){
+ if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
+ }
+ }
+ break;
}
return WRC_Continue;
}
@@ -88106,7 +91082,6 @@ SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker *pWalker, Select *p){
if( sqlite3WalkExpr(pWalker, p->pHaving) ) return WRC_Abort;
if( sqlite3WalkExprList(pWalker, p->pOrderBy) ) return WRC_Abort;
if( sqlite3WalkExpr(pWalker, p->pLimit) ) return WRC_Abort;
- if( sqlite3WalkExpr(pWalker, p->pOffset) ) return WRC_Abort;
return WRC_Continue;
}
@@ -88123,16 +91098,15 @@ SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
struct SrcList_item *pItem;
pSrc = p->pSrc;
- if( ALWAYS(pSrc) ){
- for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
- if( sqlite3WalkSelect(pWalker, pItem->pSelect) ){
- return WRC_Abort;
- }
- if( pItem->fg.isTabFunc
- && sqlite3WalkExprList(pWalker, pItem->u1.pFuncArg)
- ){
- return WRC_Abort;
- }
+ assert( pSrc!=0 );
+ for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
+ if( pItem->pSelect && sqlite3WalkSelect(pWalker, pItem->pSelect) ){
+ return WRC_Abort;
+ }
+ if( pItem->fg.isTabFunc
+ && sqlite3WalkExprList(pWalker, pItem->u1.pFuncArg)
+ ){
+ return WRC_Abort;
}
}
return WRC_Continue;
@@ -88145,8 +91119,9 @@ SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
**
** If it is not NULL, the xSelectCallback() callback is invoked before
** the walk of the expressions and FROM clause. The xSelectCallback2()
-** method, if it is not NULL, is invoked following the walk of the
-** expressions and FROM clause.
+** method is invoked following the walk of the expressions and FROM clause,
+** but only if both xSelectCallback and xSelectCallback2 are both non-NULL
+** and if the expressions and FROM clause both return WRC_Continue;
**
** Return WRC_Continue under normal conditions. Return WRC_Abort if
** there is an abort request.
@@ -88156,29 +91131,22 @@ SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
*/
SQLITE_PRIVATE int sqlite3WalkSelect(Walker *pWalker, Select *p){
int rc;
- if( p==0 || (pWalker->xSelectCallback==0 && pWalker->xSelectCallback2==0) ){
- return WRC_Continue;
- }
- rc = WRC_Continue;
- pWalker->walkerDepth++;
- while( p ){
- if( pWalker->xSelectCallback ){
- rc = pWalker->xSelectCallback(pWalker, p);
- if( rc ) break;
- }
+ if( p==0 ) return WRC_Continue;
+ if( pWalker->xSelectCallback==0 ) return WRC_Continue;
+ do{
+ rc = pWalker->xSelectCallback(pWalker, p);
+ if( rc ) return rc & WRC_Abort;
if( sqlite3WalkSelectExpr(pWalker, p)
|| sqlite3WalkSelectFrom(pWalker, p)
){
- pWalker->walkerDepth--;
return WRC_Abort;
}
if( pWalker->xSelectCallback2 ){
pWalker->xSelectCallback2(pWalker, p);
}
p = p->pPrior;
- }
- pWalker->walkerDepth--;
- return rc & WRC_Abort;
+ }while( p!=0 );
+ return WRC_Continue;
}
/************** End of walker.c **********************************************/
@@ -88200,8 +91168,6 @@ SQLITE_PRIVATE int sqlite3WalkSelect(Walker *pWalker, Select *p){
** table and column.
*/
/* #include "sqliteInt.h" */
-/* #include */
-/* #include */
/*
** Walk the expression tree pExpr and increase the aggregate function
@@ -88416,7 +91382,8 @@ static int lookupName(
}
/* Start at the inner-most context and move outward until a match is found */
- while( pNC && cnt==0 ){
+ assert( pNC && cnt==0 );
+ do{
ExprList *pEList;
SrcList *pSrcList = pNC->pSrcList;
@@ -88601,11 +91568,11 @@ static int lookupName(
/* Advance to the next name context. The loop will exit when either
** we have a match (cnt>0) or when we run out of name contexts.
*/
- if( cnt==0 ){
- pNC = pNC->pNext;
- nSubquery++;
- }
- }
+ if( cnt ) break;
+ pNC = pNC->pNext;
+ nSubquery++;
+ }while( pNC );
+
/*
** If X and Y are NULL (in other words if only the column name Z is
@@ -88664,6 +91631,7 @@ static int lookupName(
sqlite3ExprDelete(db, pExpr->pRight);
pExpr->pRight = 0;
pExpr->op = (isTrigger ? TK_TRIGGER : TK_COLUMN);
+ ExprSetProperty(pExpr, EP_Leaf);
lookupname_end:
if( cnt==1 ){
assert( pNC!=0 );
@@ -88702,7 +91670,6 @@ SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *db, SrcList *pSrc, int iSr
testcase( iCol==BMS-1 );
pItem->colUsed |= ((Bitmask)1)<<(iCol>=BMS ? BMS-1 : iCol);
}
- ExprSetProperty(p, EP_Resolved);
}
return p;
}
@@ -88762,8 +91729,6 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
pParse = pNC->pParse;
assert( pParse==pWalker->pParse );
- if( ExprHasProperty(pExpr, EP_Resolved) ) return WRC_Prune;
- ExprSetProperty(pExpr, EP_Resolved);
#ifndef NDEBUG
if( pNC->pSrcList && pNC->pSrcList->nAlloc>0 ){
SrcList *pSrcList = pNC->pSrcList;
@@ -88784,7 +91749,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
SrcList *pSrcList = pNC->pSrcList;
struct SrcList_item *pItem;
assert( pSrcList && pSrcList->nSrc==1 );
- pItem = pSrcList->a;
+ pItem = pSrcList->a;
+ assert( HasRowid(pItem->pTab) && pItem->pTab->pSelect==0 );
pExpr->op = TK_COLUMN;
pExpr->pTab = pItem->pTab;
pExpr->iTable = pItem->iCursor;
@@ -88795,33 +91761,38 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT)
&& !defined(SQLITE_OMIT_SUBQUERY) */
- /* A lone identifier is the name of a column.
- */
- case TK_ID: {
- return lookupName(pParse, 0, 0, pExpr->u.zToken, pNC, pExpr);
- }
-
- /* A table name and column name: ID.ID
+ /* A column name: ID
+ ** Or table name and column name: ID.ID
** Or a database, table and column: ID.ID.ID
+ **
+ ** The TK_ID and TK_OUT cases are combined so that there will only
+ ** be one call to lookupName(). Then the compiler will in-line
+ ** lookupName() for a size reduction and performance increase.
*/
+ case TK_ID:
case TK_DOT: {
const char *zColumn;
const char *zTable;
const char *zDb;
Expr *pRight;
- /* if( pSrcList==0 ) break; */
- notValid(pParse, pNC, "the \".\" operator", NC_IdxExpr);
- pRight = pExpr->pRight;
- if( pRight->op==TK_ID ){
+ if( pExpr->op==TK_ID ){
zDb = 0;
- zTable = pExpr->pLeft->u.zToken;
- zColumn = pRight->u.zToken;
+ zTable = 0;
+ zColumn = pExpr->u.zToken;
}else{
- assert( pRight->op==TK_DOT );
- zDb = pExpr->pLeft->u.zToken;
- zTable = pRight->pLeft->u.zToken;
- zColumn = pRight->pRight->u.zToken;
+ notValid(pParse, pNC, "the \".\" operator", NC_IdxExpr);
+ pRight = pExpr->pRight;
+ if( pRight->op==TK_ID ){
+ zDb = 0;
+ zTable = pExpr->pLeft->u.zToken;
+ zColumn = pRight->u.zToken;
+ }else{
+ assert( pRight->op==TK_DOT );
+ zDb = pExpr->pLeft->u.zToken;
+ zTable = pRight->pLeft->u.zToken;
+ zColumn = pRight->pRight->u.zToken;
+ }
}
return lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr);
}
@@ -89091,7 +92062,7 @@ static int resolveOrderByTermToExprList(
** result-set entry.
*/
for(i=0; inExpr; i++){
- if( sqlite3ExprCompare(pEList->a[i].pExpr, pE, -1)<2 ){
+ if( sqlite3ExprCompare(0, pEList->a[i].pExpr, pE, -1)<2 ){
return i+1;
}
}
@@ -89142,12 +92113,10 @@ static int resolveCompoundOrderBy(
pOrderBy = pSelect->pOrderBy;
if( pOrderBy==0 ) return 0;
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;
}
-#endif
for(i=0; inExpr; i++){
pOrderBy->a[i].done = 0;
}
@@ -89239,12 +92208,10 @@ SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(
struct ExprList_item *pItem;
if( pOrderBy==0 || pParse->db->mallocFailed ) return 0;
-#if SQLITE_MAX_COLUMN
if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
sqlite3ErrorMsg(pParse, "too many terms in %s BY clause", zType);
return 1;
}
-#endif
pEList = pSelect->pEList;
assert( pEList!=0 ); /* sqlite3SelectNew() guarantees this */
for(i=0, pItem=pOrderBy->a; inExpr; i++, pItem++){
@@ -89325,7 +92292,7 @@ static int resolveOrderGroupBy(
return 1;
}
for(j=0; jpEList->nExpr; j++){
- if( sqlite3ExprCompare(pE, pSelect->pEList->a[j].pExpr, -1)==0 ){
+ if( sqlite3ExprCompare(0, pE, pSelect->pEList->a[j].pExpr, -1)==0 ){
pItem->u.x.iOrderByCol = j+1;
}
}
@@ -89382,8 +92349,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
*/
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = pParse;
- if( sqlite3ResolveExprNames(&sNC, p->pLimit) ||
- sqlite3ResolveExprNames(&sNC, p->pOffset) ){
+ if( sqlite3ResolveExprNames(&sNC, p->pLimit) ){
return WRC_Abort;
}
@@ -89611,37 +92577,29 @@ SQLITE_PRIVATE int sqlite3ResolveExprNames(
u16 savedHasAgg;
Walker w;
- if( pExpr==0 ) return 0;
-#if SQLITE_MAX_EXPR_DEPTH>0
- {
- Parse *pParse = pNC->pParse;
- if( sqlite3ExprCheckHeight(pParse, pExpr->nHeight+pNC->pParse->nHeight) ){
- return 1;
- }
- pParse->nHeight += pExpr->nHeight;
- }
-#endif
+ if( pExpr==0 ) return SQLITE_OK;
savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg);
pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg);
w.pParse = pNC->pParse;
w.xExprCallback = resolveExprStep;
w.xSelectCallback = resolveSelectStep;
w.xSelectCallback2 = 0;
- w.walkerDepth = 0;
- w.eCode = 0;
w.u.pNC = pNC;
+#if SQLITE_MAX_EXPR_DEPTH>0
+ w.pParse->nHeight += pExpr->nHeight;
+ if( sqlite3ExprCheckHeight(w.pParse, w.pParse->nHeight) ){
+ return SQLITE_ERROR;
+ }
+#endif
sqlite3WalkExpr(&w, pExpr);
#if SQLITE_MAX_EXPR_DEPTH>0
- pNC->pParse->nHeight -= pExpr->nHeight;
+ w.pParse->nHeight -= pExpr->nHeight;
#endif
- if( pNC->nErr>0 || w.pParse->nErr>0 ){
- ExprSetProperty(pExpr, EP_Error);
- }
if( pNC->ncFlags & NC_HasAgg ){
ExprSetProperty(pExpr, EP_Agg);
}
pNC->ncFlags |= savedHasAgg;
- return ExprHasProperty(pExpr, EP_Error);
+ return pNC->nErr>0 || w.pParse->nErr>0;
}
/*
@@ -89682,9 +92640,9 @@ SQLITE_PRIVATE void sqlite3ResolveSelectNames(
Walker w;
assert( p!=0 );
- memset(&w, 0, sizeof(w));
w.xExprCallback = resolveExprStep;
w.xSelectCallback = resolveSelectStep;
+ w.xSelectCallback2 = 0;
w.pParse = pParse;
w.u.pNC = pOuterNC;
sqlite3WalkSelect(&w, p);
@@ -89787,7 +92745,7 @@ SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){
return sqlite3AffinityType(pExpr->u.zToken, 0);
}
#endif
- if( op==TK_AGG_COLUMN || op==TK_COLUMN ){
+ if( (op==TK_AGG_COLUMN || op==TK_COLUMN) && pExpr->pTab ){
return sqlite3TableColumnAffinity(pExpr->pTab, pExpr->iColumn);
}
if( op==TK_SELECT_COLUMN ){
@@ -89853,6 +92811,11 @@ SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr *pExpr){
** Return the collation sequence for the expression pExpr. If
** there is no defined collating sequence, return NULL.
**
+** See also: sqlite3ExprNNCollSeq()
+**
+** The sqlite3ExprNNCollSeq() works the same exact that it returns the
+** default collation if pExpr has no defined collation.
+**
** The collating sequence might be determined by a COLLATE operator
** or by the presence of a column with a defined collating sequence.
** COLLATE operators take first precedence. Left operands take
@@ -89917,6 +92880,32 @@ SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
return pColl;
}
+/*
+** Return the collation sequence for the expression pExpr. If
+** there is no defined collating sequence, return a pointer to the
+** defautl collation sequence.
+**
+** See also: sqlite3ExprCollSeq()
+**
+** The sqlite3ExprCollSeq() routine works the same except that it
+** returns NULL if there is no defined collation.
+*/
+SQLITE_PRIVATE CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, Expr *pExpr){
+ CollSeq *p = sqlite3ExprCollSeq(pParse, pExpr);
+ if( p==0 ) p = pParse->db->pDfltColl;
+ assert( p!=0 );
+ return p;
+}
+
+/*
+** Return TRUE if the two expressions have equivalent collating sequences.
+*/
+SQLITE_PRIVATE int sqlite3ExprCollSeqMatch(Parse *pParse, Expr *pE1, Expr *pE2){
+ CollSeq *pColl1 = sqlite3ExprNNCollSeq(pParse, pE1);
+ CollSeq *pColl2 = sqlite3ExprNNCollSeq(pParse, pE2);
+ return sqlite3StrICmp(pColl1->zName, pColl2->zName)==0;
+}
+
/*
** pExpr is an operand of a comparison operator. aff2 is the
** type affinity of the other operand. This routine returns the
@@ -89960,7 +92949,7 @@ static char comparisonAffinity(Expr *pExpr){
aff = sqlite3CompareAffinity(pExpr->pRight, aff);
}else if( ExprHasProperty(pExpr, EP_xIsSelect) ){
aff = sqlite3CompareAffinity(pExpr->x.pSelect->pEList->a[0].pExpr, aff);
- }else if( NEVER(aff==0) ){
+ }else if( aff==0 ){
aff = SQLITE_AFF_BLOB;
}
return aff;
@@ -90081,7 +93070,6 @@ SQLITE_PRIVATE int sqlite3ExprVectorSize(Expr *pExpr){
}
}
-#ifndef SQLITE_OMIT_SUBQUERY
/*
** Return a pointer to a subexpression of pVector that is the i-th
** column of the vector (numbered starting with 0). The caller must
@@ -90109,9 +93097,7 @@ SQLITE_PRIVATE Expr *sqlite3VectorFieldSubexpr(Expr *pVector, int i){
}
return pVector;
}
-#endif /* !defined(SQLITE_OMIT_SUBQUERY) */
-#ifndef SQLITE_OMIT_SUBQUERY
/*
** Compute and return a new Expr object which when passed to
** sqlite3ExprCode() will generate all necessary code to compute
@@ -90143,9 +93129,10 @@ SQLITE_PRIVATE Expr *sqlite3ExprForVectorField(
assert( pVector->flags & EP_xIsSelect );
/* The TK_SELECT_COLUMN Expr node:
**
- ** pLeft: pVector containing TK_SELECT
+ ** pLeft: pVector containing TK_SELECT. Not deleted.
** pRight: not used. But recursively deleted.
** iColumn: Index of a column in pVector
+ ** iTable: 0 or the number of columns on the LHS of an assignment
** pLeft->iTable: First in an array of register holding result, or 0
** if the result is not yet computed.
**
@@ -90156,7 +93143,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprForVectorField(
** with the same pLeft pointer to the pVector, but only one of them
** will own the pVector.
*/
- pRet = sqlite3PExpr(pParse, TK_SELECT_COLUMN, 0, 0, 0);
+ pRet = sqlite3PExpr(pParse, TK_SELECT_COLUMN, 0, 0);
if( pRet ){
pRet->iColumn = iField;
pRet->pLeft = pVector;
@@ -90168,7 +93155,6 @@ SQLITE_PRIVATE Expr *sqlite3ExprForVectorField(
}
return pRet;
}
-#endif /* !define(SQLITE_OMIT_SUBQUERY) */
/*
** If expression pExpr is of type TK_SELECT, generate code to evaluate
@@ -90256,7 +93242,10 @@ static void codeVectorCompare(
u8 opx = op;
int addrDone = sqlite3VdbeMakeLabel(v);
- assert( nLeft==sqlite3ExprVectorSize(pRight) );
+ if( nLeft!=sqlite3ExprVectorSize(pRight) ){
+ sqlite3ErrorMsg(pParse, "row value misused");
+ return;
+ }
assert( pExpr->op==TK_EQ || pExpr->op==TK_NE
|| pExpr->op==TK_IS || pExpr->op==TK_ISNOT
|| pExpr->op==TK_LT || pExpr->op==TK_GT
@@ -90356,16 +93345,15 @@ static void heightOfExprList(ExprList *p, int *pnHeight){
}
}
}
-static void heightOfSelect(Select *p, int *pnHeight){
- if( p ){
+static void heightOfSelect(Select *pSelect, int *pnHeight){
+ Select *p;
+ for(p=pSelect; p; p=p->pPrior){
heightOfExpr(p->pWhere, pnHeight);
heightOfExpr(p->pHaving, pnHeight);
heightOfExpr(p->pLimit, pnHeight);
- heightOfExpr(p->pOffset, pnHeight);
heightOfExprList(p->pEList, pnHeight);
heightOfExprList(p->pGroupBy, pnHeight);
heightOfExprList(p->pOrderBy, pnHeight);
- heightOfSelect(p->pPrior, pnHeight);
}
}
@@ -90473,7 +93461,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprAlloc(
pNew->iAgg = -1;
if( pToken ){
if( nExtra==0 ){
- pNew->flags |= EP_IntValue;
+ pNew->flags |= EP_IntValue|EP_Leaf;
pNew->u.iValue = iValue;
}else{
pNew->u.zToken = (char*)&pNew[1];
@@ -90504,7 +93492,7 @@ SQLITE_PRIVATE Expr *sqlite3Expr(
){
Token x;
x.z = zToken;
- x.n = zToken ? sqlite3Strlen30(zToken) : 0;
+ x.n = sqlite3Strlen30(zToken);
return sqlite3ExprAlloc(db, op, &x, 0);
}
@@ -90548,15 +93536,19 @@ SQLITE_PRIVATE Expr *sqlite3PExpr(
Parse *pParse, /* Parsing context */
int op, /* Expression opcode */
Expr *pLeft, /* Left operand */
- Expr *pRight, /* Right operand */
- const Token *pToken /* Argument token */
+ Expr *pRight /* Right operand */
){
Expr *p;
if( op==TK_AND && pParse->nErr==0 ){
/* Take advantage of short-circuit false optimization for AND */
p = sqlite3ExprAnd(pParse->db, pLeft, pRight);
}else{
- p = sqlite3ExprAlloc(pParse->db, op & TKFLG_MASK, pToken, 1);
+ p = sqlite3DbMallocRawNN(pParse->db, sizeof(Expr));
+ if( p ){
+ memset(p, 0, sizeof(Expr));
+ p->op = op & TKFLG_MASK;
+ p->iAgg = -1;
+ }
sqlite3ExprAttachSubtrees(pParse->db, p, pLeft, pRight);
}
if( p ) {
@@ -90646,6 +93638,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *
return 0;
}
pNew->x.pList = pList;
+ ExprSetProperty(pNew, EP_HasFunc);
assert( !ExprHasProperty(pNew, EP_xIsSelect) );
sqlite3ExprSetHeightAndFlags(pParse, pNew);
return pNew;
@@ -90659,7 +93652,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *
** variable number.
**
** Wildcards of the form "?nnn" are assigned the number "nnn". We make
-** sure "nnn" is not too be to avoid a denial of service attack when
+** sure "nnn" is not too big to avoid a denial of service attack when
** the SQL statement comes from an external source.
**
** Wildcards of the form ":aaa", "@aaa", or "$aaa" are assigned the same number
@@ -90670,25 +93663,31 @@ SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *
SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr, u32 n){
sqlite3 *db = pParse->db;
const char *z;
+ ynVar x;
if( pExpr==0 ) return;
assert( !ExprHasProperty(pExpr, EP_IntValue|EP_Reduced|EP_TokenOnly) );
z = pExpr->u.zToken;
assert( z!=0 );
assert( z[0]!=0 );
- assert( n==sqlite3Strlen30(z) );
+ assert( n==(u32)sqlite3Strlen30(z) );
if( z[1]==0 ){
/* Wildcard of the form "?". Assign the next variable number */
assert( z[0]=='?' );
- pExpr->iColumn = (ynVar)(++pParse->nVar);
+ x = (ynVar)(++pParse->nVar);
}else{
- ynVar x;
+ int doAdd = 0;
if( z[0]=='?' ){
/* Wildcard of the form "?nnn". Convert "nnn" to an integer and
** use it as the variable number */
i64 i;
- int bOk = 0==sqlite3Atoi64(&z[1], &i, n-1, SQLITE_UTF8);
- x = (ynVar)i;
+ int bOk;
+ if( n==2 ){ /*OPTIMIZATION-IF-TRUE*/
+ i = z[1]-'0'; /* The common case of ?N for a single digit N */
+ bOk = 1;
+ }else{
+ bOk = 0==sqlite3Atoi64(&z[1], &i, n-1, SQLITE_UTF8);
+ }
testcase( i==0 );
testcase( i==1 );
testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 );
@@ -90698,40 +93697,30 @@ SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr, u32 n
db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]);
return;
}
- if( i>pParse->nVar ){
- pParse->nVar = (int)i;
+ x = (ynVar)i;
+ if( x>pParse->nVar ){
+ pParse->nVar = (int)x;
+ doAdd = 1;
+ }else if( sqlite3VListNumToName(pParse->pVList, x)==0 ){
+ doAdd = 1;
}
}else{
/* Wildcards like ":aaa", "$aaa" or "@aaa". Reuse the same variable
** number as the prior appearance of the same name, or if the name
** has never appeared before, reuse the same variable number
*/
- ynVar i;
- for(i=x=0; inzVar; i++){
- if( pParse->azVar[i] && strcmp(pParse->azVar[i],z)==0 ){
- x = (ynVar)i+1;
- break;
- }
- }
- if( x==0 ) x = (ynVar)(++pParse->nVar);
- }
- pExpr->iColumn = x;
- if( x>pParse->nzVar ){
- char **a;
- a = sqlite3DbRealloc(db, pParse->azVar, x*sizeof(a[0]));
- if( a==0 ){
- assert( db->mallocFailed ); /* Error reported through mallocFailed */
- return;
+ x = (ynVar)sqlite3VListNameToNum(pParse->pVList, z, n);
+ if( x==0 ){
+ x = (ynVar)(++pParse->nVar);
+ doAdd = 1;
}
- pParse->azVar = a;
- memset(&a[pParse->nzVar], 0, (x-pParse->nzVar)*sizeof(a[0]));
- pParse->nzVar = x;
}
- if( pParse->azVar[x-1]==0 ){
- pParse->azVar[x-1] = sqlite3DbStrNDup(db, z, n);
+ if( doAdd ){
+ pParse->pVList = sqlite3VListAdd(db, pParse->pVList, z, n, x);
}
- }
- if( pParse->nVar>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
+ }
+ pExpr->iColumn = x;
+ if( x>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
sqlite3ErrorMsg(pParse, "too many SQL variables");
}
}
@@ -90754,8 +93743,9 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
/* The Expr.x union is never used at the same time as Expr.pRight */
assert( p->x.pList==0 || p->pRight==0 );
if( p->pLeft && p->op!=TK_SELECT_COLUMN ) sqlite3ExprDeleteNN(db, p->pLeft);
- sqlite3ExprDelete(db, p->pRight);
- if( ExprHasProperty(p, EP_xIsSelect) ){
+ if( p->pRight ){
+ sqlite3ExprDeleteNN(db, p->pRight);
+ }else if( ExprHasProperty(p, EP_xIsSelect) ){
sqlite3SelectDelete(db, p->x.pSelect);
}else{
sqlite3ExprListDelete(db, p->x.pList);
@@ -90763,7 +93753,7 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
}
if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken);
if( !ExprHasProperty(p, EP_Static) ){
- sqlite3DbFree(db, p);
+ sqlite3DbFreeNN(db, p);
}
}
SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3 *db, Expr *p){
@@ -90820,7 +93810,7 @@ static int dupedExprStructSize(Expr *p, int flags){
assert( flags==EXPRDUP_REDUCE || flags==0 ); /* Only one flag value allowed */
assert( EXPR_FULLSIZE<=0xfff );
assert( (0xfff & (EP_Reduced|EP_TokenOnly))==0 );
- if( 0==flags ){
+ if( 0==flags || p->op==TK_SELECT_COLUMN ){
nSize = EXPR_FULLSIZE;
}else{
assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
@@ -90963,6 +93953,8 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){
if( pNew->op==TK_SELECT_COLUMN ){
pNew->pLeft = p->pLeft;
+ assert( p->iColumn==0 || p->pRight==0 );
+ assert( p->pRight==0 || p->pRight==p->pLeft );
}else{
pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0);
}
@@ -91025,21 +94017,34 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags)
ExprList *pNew;
struct ExprList_item *pItem, *pOldItem;
int i;
+ Expr *pPriorSelectCol = 0;
assert( db!=0 );
if( p==0 ) return 0;
- pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew) );
+ pNew = sqlite3DbMallocRawNN(db, sqlite3DbMallocSize(db, p));
if( pNew==0 ) return 0;
- pNew->nExpr = i = p->nExpr;
- if( (flags & EXPRDUP_REDUCE)==0 ) for(i=1; inExpr; i+=i){}
- pNew->a = pItem = sqlite3DbMallocRawNN(db, i*sizeof(p->a[0]) );
- if( pItem==0 ){
- sqlite3DbFree(db, pNew);
- return 0;
- }
+ pNew->nExpr = p->nExpr;
+ pItem = pNew->a;
pOldItem = p->a;
for(i=0; inExpr; i++, pItem++, pOldItem++){
Expr *pOldExpr = pOldItem->pExpr;
+ Expr *pNewExpr;
pItem->pExpr = sqlite3ExprDup(db, pOldExpr, flags);
+ if( pOldExpr
+ && pOldExpr->op==TK_SELECT_COLUMN
+ && (pNewExpr = pItem->pExpr)!=0
+ ){
+ assert( pNewExpr->iColumn==0 || i>0 );
+ if( pNewExpr->iColumn==0 ){
+ assert( pOldExpr->pLeft==pOldExpr->pRight );
+ pPriorSelectCol = pNewExpr->pLeft = pNewExpr->pRight;
+ }else{
+ assert( i>0 );
+ assert( pItem[-1].pExpr!=0 );
+ assert( pNewExpr->iColumn==pItem[-1].pExpr->iColumn+1 );
+ assert( pPriorSelectCol==pItem[-1].pExpr->pLeft );
+ pNewExpr->pLeft = pPriorSelectCol;
+ }
+ }
pItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
pItem->zSpan = sqlite3DbStrDup(db, pOldItem->zSpan);
pItem->sortOrder = pOldItem->sortOrder;
@@ -91090,7 +94095,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){
}
pTab = pNewItem->pTab = pOldItem->pTab;
if( pTab ){
- pTab->nRef++;
+ pTab->nTabRef++;
}
pNewItem->pSelect = sqlite3SelectDup(db, pOldItem->pSelect, flags);
pNewItem->pOn = sqlite3ExprDup(db, pOldItem->pOn, flags);
@@ -91109,7 +94114,7 @@ SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3 *db, IdList *p){
pNew->nId = p->nId;
pNew->a = sqlite3DbMallocRawNN(db, p->nId*sizeof(p->a[0]) );
if( pNew->a==0 ){
- sqlite3DbFree(db, pNew);
+ sqlite3DbFreeNN(db, pNew);
return 0;
}
/* Note that because the size of the allocation for p->a[] is not
@@ -91123,33 +94128,40 @@ SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3 *db, IdList *p){
}
return pNew;
}
-SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
- Select *pNew, *pPrior;
+SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *pDup, int flags){
+ Select *pRet = 0;
+ Select *pNext = 0;
+ Select **pp = &pRet;
+ Select *p;
+
assert( db!=0 );
- if( p==0 ) return 0;
- pNew = sqlite3DbMallocRawNN(db, sizeof(*p) );
- if( pNew==0 ) return 0;
- pNew->pEList = sqlite3ExprListDup(db, p->pEList, flags);
- pNew->pSrc = sqlite3SrcListDup(db, p->pSrc, flags);
- pNew->pWhere = sqlite3ExprDup(db, p->pWhere, flags);
- pNew->pGroupBy = sqlite3ExprListDup(db, p->pGroupBy, flags);
- pNew->pHaving = sqlite3ExprDup(db, p->pHaving, flags);
- pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy, flags);
- pNew->op = p->op;
- pNew->pPrior = pPrior = sqlite3SelectDup(db, p->pPrior, flags);
- if( pPrior ) pPrior->pNext = pNew;
- pNew->pNext = 0;
- pNew->pLimit = sqlite3ExprDup(db, p->pLimit, flags);
- pNew->pOffset = sqlite3ExprDup(db, p->pOffset, flags);
- pNew->iLimit = 0;
- pNew->iOffset = 0;
- pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
- pNew->addrOpenEphm[0] = -1;
- pNew->addrOpenEphm[1] = -1;
- pNew->nSelectRow = p->nSelectRow;
- pNew->pWith = withDup(db, p->pWith);
- sqlite3SelectSetName(pNew, p->zSelName);
- return pNew;
+ for(p=pDup; p; p=p->pPrior){
+ Select *pNew = sqlite3DbMallocRawNN(db, sizeof(*p) );
+ if( pNew==0 ) break;
+ pNew->pEList = sqlite3ExprListDup(db, p->pEList, flags);
+ pNew->pSrc = sqlite3SrcListDup(db, p->pSrc, flags);
+ pNew->pWhere = sqlite3ExprDup(db, p->pWhere, flags);
+ pNew->pGroupBy = sqlite3ExprListDup(db, p->pGroupBy, flags);
+ pNew->pHaving = sqlite3ExprDup(db, p->pHaving, flags);
+ pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy, flags);
+ pNew->op = p->op;
+ pNew->pNext = pNext;
+ pNew->pPrior = 0;
+ pNew->pLimit = sqlite3ExprDup(db, p->pLimit, flags);
+ pNew->iLimit = 0;
+ pNew->iOffset = 0;
+ pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
+ pNew->addrOpenEphm[0] = -1;
+ pNew->addrOpenEphm[1] = -1;
+ pNew->nSelectRow = p->nSelectRow;
+ pNew->pWith = withDup(db, p->pWith);
+ sqlite3SelectSetName(pNew, p->zSelName);
+ *pp = pNew;
+ pp = &pNew->pPrior;
+ pNext = pNew;
+ }
+
+ return pRet;
}
#else
SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
@@ -91163,6 +94175,13 @@ SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
** Add a new element to the end of an expression list. If pList is
** initially NULL, then create a new expression list.
**
+** The pList argument must be either NULL or a pointer to an ExprList
+** obtained from a prior call to sqlite3ExprListAppend(). This routine
+** may not be used with an ExprList obtained from sqlite3ExprListDup().
+** Reason: This routine assumes that the number of slots in pList->a[]
+** is a power of two. That is true for sqlite3ExprListAppend() returns
+** but is not necessarily true from the return value of sqlite3ExprListDup().
+**
** If a memory allocation error occurs, the entire list is freed and
** NULL is returned. If non-NULL is returned, then it is guaranteed
** that the new entry was successfully appended.
@@ -91172,6 +94191,7 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(
ExprList *pList, /* List to which to append. Might be NULL */
Expr *pExpr /* Expression to be appended. Might be NULL */
){
+ struct ExprList_item *pItem;
sqlite3 *db = pParse->db;
assert( db!=0 );
if( pList==0 ){
@@ -91180,23 +94200,20 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(
goto no_mem;
}
pList->nExpr = 0;
- pList->a = sqlite3DbMallocRawNN(db, sizeof(pList->a[0]));
- if( pList->a==0 ) goto no_mem;
}else if( (pList->nExpr & (pList->nExpr-1))==0 ){
- struct ExprList_item *a;
- assert( pList->nExpr>0 );
- a = sqlite3DbRealloc(db, pList->a, pList->nExpr*2*sizeof(pList->a[0]));
- if( a==0 ){
+ ExprList *pNew;
+ pNew = sqlite3DbRealloc(db, pList,
+ sizeof(*pList)+(2*pList->nExpr - 1)*sizeof(pList->a[0]));
+ if( pNew==0 ){
goto no_mem;
}
- pList->a = a;
- }
- assert( pList->a!=0 );
- if( 1 ){
- struct ExprList_item *pItem = &pList->a[pList->nExpr++];
- memset(pItem, 0, sizeof(*pItem));
- pItem->pExpr = pExpr;
+ pList = pNew;
}
+ pItem = &pList->a[pList->nExpr++];
+ assert( offsetof(struct ExprList_item,zName)==sizeof(pItem->pExpr) );
+ assert( offsetof(struct ExprList_item,pExpr)==0 );
+ memset(&pItem->zName,0,sizeof(*pItem)-offsetof(struct ExprList_item,zName));
+ pItem->pExpr = pExpr;
return pList;
no_mem:
@@ -91214,7 +94231,7 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(
** Or: (a,b,c) = (SELECT x,y,z FROM ....)
**
** For each term of the vector assignment, append new entries to the
-** expression list pList. In the case of a subquery on the LHS, append
+** expression list pList. In the case of a subquery on the RHS, append
** TK_SELECT_COLUMN expressions.
*/
SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector(
@@ -91231,13 +94248,19 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector(
** exit prior to this routine being invoked */
if( NEVER(pColumns==0) ) goto vector_append_error;
if( pExpr==0 ) goto vector_append_error;
- n = sqlite3ExprVectorSize(pExpr);
- if( pColumns->nId!=n ){
+
+ /* If the RHS is a vector, then we can immediately check to see that
+ ** the size of the RHS and LHS match. But if the RHS is a SELECT,
+ ** wildcards ("*") in the result set of the SELECT must be expanded before
+ ** we can do the size check, so defer the size check until code generation.
+ */
+ if( pExpr->op!=TK_SELECT && pColumns->nId!=(n=sqlite3ExprVectorSize(pExpr)) ){
sqlite3ErrorMsg(pParse, "%d columns assigned %d values",
pColumns->nId, n);
goto vector_append_error;
}
- for(i=0; inId; i++){
Expr *pSubExpr = sqlite3ExprForVectorField(pParse, pExpr, i);
pList = sqlite3ExprListAppend(pParse, pList, pSubExpr);
if( pList ){
@@ -91246,12 +94269,20 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector(
pColumns->a[i].zName = 0;
}
}
- if( pExpr->op==TK_SELECT ){
- if( pList && pList->a[iFirst].pExpr ){
- assert( pList->a[iFirst].pExpr->op==TK_SELECT_COLUMN );
- pList->a[iFirst].pExpr->pRight = pExpr;
- pExpr = 0;
- }
+
+ if( !db->mallocFailed && pExpr->op==TK_SELECT && ALWAYS(pList!=0) ){
+ Expr *pFirst = pList->a[iFirst].pExpr;
+ assert( pFirst!=0 );
+ assert( pFirst->op==TK_SELECT_COLUMN );
+
+ /* Store the SELECT statement in pRight so it will be deleted when
+ ** sqlite3ExprListDelete() is called */
+ pFirst->pRight = pExpr;
+ pExpr = 0;
+
+ /* Remember the size of the LHS in iTable so that we can check that
+ ** the RHS and LHS sizes match during code generation. */
+ pFirst->iTable = pColumns->nId;
}
vector_append_error:
@@ -91310,17 +94341,16 @@ SQLITE_PRIVATE void sqlite3ExprListSetName(
SQLITE_PRIVATE void sqlite3ExprListSetSpan(
Parse *pParse, /* Parsing context */
ExprList *pList, /* List to which to add the span. */
- ExprSpan *pSpan /* The span to be added */
+ const char *zStart, /* Start of the span */
+ const char *zEnd /* End of the span */
){
sqlite3 *db = pParse->db;
assert( pList!=0 || db->mallocFailed!=0 );
if( pList ){
struct ExprList_item *pItem = &pList->a[pList->nExpr-1];
assert( pList->nExpr>0 );
- assert( db->mallocFailed || pItem->pExpr==pSpan->pExpr );
sqlite3DbFree(db, pItem->zSpan);
- pItem->zSpan = sqlite3DbStrNDup(db, (char*)pSpan->zStart,
- (int)(pSpan->zEnd - pSpan->zStart));
+ pItem->zSpan = sqlite3DbSpanDup(db, zStart, zEnd);
}
}
@@ -91345,16 +94375,16 @@ SQLITE_PRIVATE void sqlite3ExprListCheckLength(
** Delete an entire expression list.
*/
static SQLITE_NOINLINE void exprListDeleteNN(sqlite3 *db, ExprList *pList){
- int i;
- struct ExprList_item *pItem;
- assert( pList->a!=0 || pList->nExpr==0 );
- for(pItem=pList->a, i=0; inExpr; i++, pItem++){
+ int i = pList->nExpr;
+ struct ExprList_item *pItem = pList->a;
+ assert( pList->nExpr>0 );
+ do{
sqlite3ExprDelete(db, pItem->pExpr);
sqlite3DbFree(db, pItem->zName);
sqlite3DbFree(db, pItem->zSpan);
- }
- sqlite3DbFree(db, pList->a);
- sqlite3DbFree(db, pList);
+ pItem++;
+ }while( --i>0 );
+ sqlite3DbFreeNN(db, pList);
}
SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){
if( pList ) exprListDeleteNN(db, pList);
@@ -91367,16 +94397,28 @@ SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){
SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList *pList){
int i;
u32 m = 0;
- if( pList ){
- for(i=0; inExpr; i++){
- Expr *pExpr = pList->a[i].pExpr;
- assert( pExpr!=0 );
- m |= pExpr->flags;
- }
+ assert( pList!=0 );
+ for(i=0; inExpr; i++){
+ Expr *pExpr = pList->a[i].pExpr;
+ assert( pExpr!=0 );
+ m |= pExpr->flags;
}
return m;
}
+/*
+** This is a SELECT-node callback for the expression walker that
+** always "fails". By "fail" in this case, we mean set
+** pWalker->eCode to zero and abort.
+**
+** This callback is used by multiple expression walkers.
+*/
+SQLITE_PRIVATE int sqlite3SelectWalkFail(Walker *pWalker, Select *NotUsed){
+ UNUSED_PARAMETER(NotUsed);
+ pWalker->eCode = 0;
+ return WRC_Abort;
+}
+
/*
** These routines are Walker callbacks used to check expressions to
** see if they are "constant" for some definition of constant. The
@@ -91433,10 +94475,12 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
testcase( pExpr->op==TK_AGG_COLUMN );
if( pWalker->eCode==3 && pExpr->iTable==pWalker->u.iCur ){
return WRC_Continue;
- }else{
- pWalker->eCode = 0;
- return WRC_Abort;
}
+ /* Fall through */
+ case TK_IF_NULL_ROW:
+ testcase( pExpr->op==TK_IF_NULL_ROW );
+ pWalker->eCode = 0;
+ return WRC_Abort;
case TK_VARIABLE:
if( pWalker->eCode==5 ){
/* Silently convert bound parameters that appear inside of CREATE
@@ -91451,22 +94495,19 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
}
/* Fall through */
default:
- testcase( pExpr->op==TK_SELECT ); /* selectNodeIsConstant will disallow */
- testcase( pExpr->op==TK_EXISTS ); /* selectNodeIsConstant will disallow */
+ testcase( pExpr->op==TK_SELECT ); /* sqlite3SelectWalkFail will disallow */
+ testcase( pExpr->op==TK_EXISTS ); /* sqlite3SelectWalkFail will disallow */
return WRC_Continue;
}
}
-static int selectNodeIsConstant(Walker *pWalker, Select *NotUsed){
- UNUSED_PARAMETER(NotUsed);
- pWalker->eCode = 0;
- return WRC_Abort;
-}
static int exprIsConst(Expr *p, int initFlag, int iCur){
Walker w;
- memset(&w, 0, sizeof(w));
w.eCode = initFlag;
w.xExprCallback = exprNodeIsConstant;
- w.xSelectCallback = selectNodeIsConstant;
+ w.xSelectCallback = sqlite3SelectWalkFail;
+#ifdef SQLITE_DEBUG
+ w.xSelectCallback2 = sqlite3SelectWalkAssert2;
+#endif
w.u.iCur = iCur;
sqlite3WalkExpr(&w, p);
return w.eCode;
@@ -91504,6 +94545,65 @@ SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr *p, int iCur){
return exprIsConst(p, 3, iCur);
}
+
+/*
+** sqlite3WalkExpr() callback used by sqlite3ExprIsConstantOrGroupBy().
+*/
+static int exprNodeIsConstantOrGroupBy(Walker *pWalker, Expr *pExpr){
+ ExprList *pGroupBy = pWalker->u.pGroupBy;
+ int i;
+
+ /* Check if pExpr is identical to any GROUP BY term. If so, consider
+ ** it constant. */
+ for(i=0; inExpr; i++){
+ Expr *p = pGroupBy->a[i].pExpr;
+ if( sqlite3ExprCompare(0, pExpr, p, -1)<2 ){
+ CollSeq *pColl = sqlite3ExprNNCollSeq(pWalker->pParse, p);
+ if( sqlite3_stricmp("BINARY", pColl->zName)==0 ){
+ return WRC_Prune;
+ }
+ }
+ }
+
+ /* Check if pExpr is a sub-select. If so, consider it variable. */
+ if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+ pWalker->eCode = 0;
+ return WRC_Abort;
+ }
+
+ return exprNodeIsConstant(pWalker, pExpr);
+}
+
+/*
+** Walk the expression tree passed as the first argument. Return non-zero
+** if the expression consists entirely of constants or copies of terms
+** in pGroupBy that sort with the BINARY collation sequence.
+**
+** This routine is used to determine if a term of the HAVING clause can
+** be promoted into the WHERE clause. In order for such a promotion to work,
+** the value of the HAVING clause term must be the same for all members of
+** a "group". The requirement that the GROUP BY term must be BINARY
+** assumes that no other collating sequence will have a finer-grained
+** grouping than binary. In other words (A=B COLLATE binary) implies
+** A=B in every other collating sequence. The requirement that the
+** GROUP BY be BINARY is stricter than necessary. It would also work
+** to promote HAVING clauses that use the same alternative collating
+** sequence as the GROUP BY term, but that is much harder to check,
+** alternative collating sequences are uncommon, and this is only an
+** optimization, so we take the easy way out and simply require the
+** GROUP BY to use the BINARY collating sequence.
+*/
+SQLITE_PRIVATE int sqlite3ExprIsConstantOrGroupBy(Parse *pParse, Expr *p, ExprList *pGroupBy){
+ Walker w;
+ w.eCode = 1;
+ w.xExprCallback = exprNodeIsConstantOrGroupBy;
+ w.xSelectCallback = 0;
+ w.u.pGroupBy = pGroupBy;
+ w.pParse = pParse;
+ sqlite3WalkExpr(&w, p);
+ return w.eCode;
+}
+
/*
** Walk an expression tree. Return non-zero if the expression is constant
** or a function call with constant arguments. Return and 0 if there
@@ -91525,10 +94625,12 @@ SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr *p, u8 isInit){
*/
SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr *p){
Walker w;
- memset(&w, 0, sizeof(w));
w.eCode = 1;
w.xExprCallback = sqlite3ExprWalkNoop;
- w.xSelectCallback = selectNodeIsConstant;
+ w.xSelectCallback = sqlite3SelectWalkFail;
+#ifdef SQLITE_DEBUG
+ w.xSelectCallback2 = sqlite3SelectWalkAssert2;
+#endif
sqlite3WalkExpr(&w, p);
return w.eCode==0;
}
@@ -91542,6 +94644,7 @@ SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr *p){
*/
SQLITE_PRIVATE int sqlite3ExprIsInteger(Expr *p, int *pValue){
int rc = 0;
+ if( p==0 ) return 0; /* Can only happen following on OOM */
/* If an expression is an integer literal that fits in a signed 32-bit
** integer, then the EP_IntValue flag will have already been set */
@@ -91597,8 +94700,8 @@ SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr *p){
case TK_BLOB:
return 0;
case TK_COLUMN:
- assert( p->pTab!=0 );
return ExprHasProperty(p, EP_CanBeNull) ||
+ p->pTab==0 || /* Reference to column of index on expression */
(p->iColumn>=0 && p->pTab->aCol[p->iColumn].notNull==0);
default:
return 1;
@@ -91680,7 +94783,6 @@ static Select *isCandidateForInOpt(Expr *pX){
}
assert( p->pGroupBy==0 ); /* Has no GROUP BY clause */
if( p->pLimit ) return 0; /* Has no LIMIT clause */
- assert( p->pOffset==0 ); /* No LIMIT means no OFFSET */
if( p->pWhere ) return 0; /* Has no WHERE clause */
pSrc = p->pSrc;
assert( pSrc!=0 );
@@ -91770,16 +94872,15 @@ static int sqlite3InRhsIsConstant(Expr *pIn){
** pX->iTable made to point to the ephemeral table instead of an
** existing table.
**
-** The inFlags parameter must contain exactly one of the bits
-** IN_INDEX_MEMBERSHIP or IN_INDEX_LOOP. If inFlags contains
-** IN_INDEX_MEMBERSHIP, then the generated table will be used for a
-** fast membership test. When the IN_INDEX_LOOP bit is set, the
-** IN index will be used to loop over all values of the RHS of the
-** IN operator.
+** The inFlags parameter must contain, at a minimum, one of the bits
+** IN_INDEX_MEMBERSHIP or IN_INDEX_LOOP but not both. If inFlags contains
+** IN_INDEX_MEMBERSHIP, then the generated table will be used for a fast
+** membership test. When the IN_INDEX_LOOP bit is set, the IN index will
+** be used to loop over all values of the RHS of the IN operator.
**
** When IN_INDEX_LOOP is used (and the b-tree will be used to iterate
** through the set members) then the b-tree must not contain duplicates.
-** An epheremal table must be used unless the selected columns are guaranteed
+** An epheremal table will be created unless the selected columns are guaranteed
** to be unique - either because it is an INTEGER PRIMARY KEY or due to
** a UNIQUE constraint or index.
**
@@ -92049,7 +95150,7 @@ static char *exprINAffinity(Parse *pParse, Expr *pExpr){
char *zRet;
assert( pExpr->op==TK_IN );
- zRet = sqlite3DbMallocZero(pParse->db, nVal+1);
+ zRet = sqlite3DbMallocRaw(pParse->db, nVal+1);
if( zRet ){
int i;
for(i=0; iflags & EP_xIsSelect ){
+ sqlite3SubselectError(pParse, pExpr->x.pSelect->pEList->nExpr, 1);
+ }else
+#endif
+ {
+ sqlite3ErrorMsg(pParse, "row value misused");
+ }
+}
+
/*
** Generate code for scalar subqueries used as a subquery expression, EXISTS,
** or IN operators. Examples:
@@ -92192,7 +95315,6 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
int i;
sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable);
dest.zAffSdst = exprINAffinity(pParse, pExpr);
- assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable );
pSelect->iLimit = 0;
testcase( pSelect->selFlags & SF_Distinct );
testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */
@@ -92239,7 +95361,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
/* Loop through each expression in . */
r1 = sqlite3GetTempReg(pParse);
r2 = sqlite3GetTempReg(pParse);
- if( isRowid ) sqlite3VdbeAddOp2(v, OP_Null, 0, r2);
+ if( isRowid ) sqlite3VdbeAddOp4(v, OP_Blob, 0, r2, 0, "", P4_STATIC);
for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){
Expr *pE2 = pItem->pExpr;
int iValToIns;
@@ -92267,7 +95389,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
}else{
sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1);
sqlite3ExprCacheAffinityChange(pParse, r3, 1);
- sqlite3VdbeAddOp2(v, OP_IdxInsert, pExpr->iTable, r2);
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pExpr->iTable, r2, r3, 1);
}
}
}
@@ -92299,6 +95421,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
Select *pSel; /* SELECT statement to encode */
SelectDest dest; /* How to deal with SELECT result */
int nReg; /* Registers to allocate */
+ Expr *pLimit; /* New limit expression */
testcase( pExpr->op==TK_EXISTS );
testcase( pExpr->op==TK_SELECT );
@@ -92320,11 +95443,14 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
sqlite3VdbeAddOp2(v, OP_Integer, 0, dest.iSDParm);
VdbeComment((v, "Init EXISTS result"));
}
- sqlite3ExprDelete(pParse->db, pSel->pLimit);
- pSel->pLimit = sqlite3ExprAlloc(pParse->db, TK_INTEGER,
- &sqlite3IntTokens[1], 0);
+ pLimit = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[1], 0);
+ if( pSel->pLimit ){
+ sqlite3ExprDelete(pParse->db, pSel->pLimit->pLeft);
+ pSel->pLimit->pLeft = pLimit;
+ }else{
+ pSel->pLimit = sqlite3PExpr(pParse, TK_LIMIT, pLimit, 0);
+ }
pSel->iLimit = 0;
- pSel->selFlags &= ~SF_MultiValue;
if( sqlite3Select(pParse, pSel, &dest) ){
return 0;
}
@@ -92362,11 +95488,7 @@ SQLITE_PRIVATE int sqlite3ExprCheckIN(Parse *pParse, Expr *pIn){
return 1;
}
}else if( nVector!=1 ){
- if( (pIn->pLeft->flags & EP_xIsSelect) ){
- sqlite3SubselectError(pParse, nVector, 1);
- }else{
- sqlite3ErrorMsg(pParse, "row value misused");
- }
+ sqlite3VectorErrorMsg(pParse, pIn->pLeft);
return 1;
}
return 0;
@@ -92671,22 +95793,22 @@ static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
const char *z = pExpr->u.zToken;
assert( z!=0 );
c = sqlite3DecOrHexToI64(z, &value);
- if( c==0 || (c==2 && negFlag) ){
- if( negFlag ){ value = c==2 ? SMALLEST_INT64 : -value; }
- sqlite3VdbeAddOp4Dup8(v, OP_Int64, 0, iMem, 0, (u8*)&value, P4_INT64);
- }else{
+ if( (c==3 && !negFlag) || (c==2) || (negFlag && value==SMALLEST_INT64)){
#ifdef SQLITE_OMIT_FLOATING_POINT
sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z);
#else
#ifndef SQLITE_OMIT_HEX_INTEGER
if( sqlite3_strnicmp(z,"0x",2)==0 ){
- sqlite3ErrorMsg(pParse, "hex literal too big: %s", z);
+ sqlite3ErrorMsg(pParse, "hex literal too big: %s%s", negFlag?"-":"",z);
}else
#endif
{
codeReal(v, z, negFlag, iMem);
}
#endif
+ }else{
+ if( negFlag ){ value = c==3 ? SMALLEST_INT64 : -value; }
+ sqlite3VdbeAddOp4Dup8(v, OP_Int64, 0, iMem, 0, (u8*)&value, P4_INT64);
}
}
}
@@ -92845,8 +95967,9 @@ SQLITE_PRIVATE void sqlite3ExprCodeLoadIndexColumn(
if( iTabCol==XN_EXPR ){
assert( pIdx->aColExpr );
assert( pIdx->aColExpr->nExpr>iIdxCol );
- pParse->iSelfTab = iTabCur;
+ pParse->iSelfTab = iTabCur + 1;
sqlite3ExprCodeCopy(pParse, pIdx->aColExpr->a[iIdxCol].pExpr, regOut);
+ pParse->iSelfTab = 0;
}else{
sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pIdx->pTable, iTabCur,
iTabCol, regOut);
@@ -92863,6 +95986,10 @@ SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(
int iCol, /* Index of the column to extract */
int regOut /* Extract the value into this register */
){
+ if( pTab==0 ){
+ sqlite3VdbeAddOp3(v, OP_Column, iTabCur, iCol, regOut);
+ return;
+ }
if( iCol<0 || iCol==pTab->iPKey ){
sqlite3VdbeAddOp2(v, OP_Rowid, iTabCur, regOut);
}else{
@@ -92936,7 +96063,7 @@ SQLITE_PRIVATE void sqlite3ExprCodeGetColumnToReg(
SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse *pParse){
int i;
-#if SQLITE_DEBUG
+#ifdef SQLITE_DEBUG
if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
printf("CLEAR\n");
}
@@ -93019,7 +96146,11 @@ static int exprCodeVector(Parse *pParse, Expr *p, int *piFreeable){
}else{
*piFreeable = 0;
if( p->op==TK_SELECT ){
+#if SQLITE_OMIT_SUBQUERY
+ iResult = 0;
+#else
iResult = sqlite3CodeSubselect(pParse, p, 0, 0);
+#endif
}else{
int i;
iResult = pParse->nMem+1;
@@ -93082,13 +96213,13 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
case TK_COLUMN: {
int iTab = pExpr->iTable;
if( iTab<0 ){
- if( pParse->ckBase>0 ){
+ if( pParse->iSelfTab<0 ){
/* Generating CHECK constraints or inserting into partial index */
- return pExpr->iColumn + pParse->ckBase;
+ return pExpr->iColumn - pParse->iSelfTab;
}else{
/* Coding an expression that is part of an index where column names
** in the index refer to the table to which the index belongs */
- iTab = pParse->iSelfTab;
+ iTab = pParse->iSelfTab - 1;
}
}
return sqlite3ExprCodeGetColumn(pParse, pExpr->pTab,
@@ -93137,9 +96268,10 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
assert( pExpr->u.zToken[0]!=0 );
sqlite3VdbeAddOp2(v, OP_Variable, pExpr->iColumn, target);
if( pExpr->u.zToken[1]!=0 ){
- assert( pExpr->u.zToken[0]=='?'
- || strcmp(pExpr->u.zToken, pParse->azVar[pExpr->iColumn-1])==0 );
- sqlite3VdbeChangeP4(v, -1, pParse->azVar[pExpr->iColumn-1], P4_STATIC);
+ const char *z = sqlite3VListNumToName(pParse->pVList, pExpr->iColumn);
+ assert( pExpr->u.zToken[0]=='?' || strcmp(pExpr->u.zToken, z)==0 );
+ pParse->pVList[0] = 0; /* Indicate VList may no longer be enlarged */
+ sqlite3VdbeAppendP4(v, (char*)z, P4_STATIC);
}
return target;
}
@@ -93289,6 +96421,11 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
u8 enc = ENC(db); /* The text encoding used by this database */
CollSeq *pColl = 0; /* A collating sequence */
+ if( ConstFactorOk(pParse) && sqlite3ExprIsConstantNotJoin(pExpr) ){
+ /* SQL functions can be expensive. So try to move constant functions
+ ** out of the inner loop, even if that means an extra OP_Copy. */
+ return sqlite3ExprCodeAtInit(pParse, pExpr, -1);
+ }
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
if( ExprHasProperty(pExpr, EP_TokenOnly) ){
pFarg = 0;
@@ -93337,6 +96474,22 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
return sqlite3ExprCodeTarget(pParse, pFarg->a[0].pExpr, target);
}
+#ifdef SQLITE_DEBUG
+ /* The AFFINITY() function evaluates to a string that describes
+ ** the type affinity of the argument. This is used for testing of
+ ** the SQLite type logic.
+ */
+ if( pDef->funcFlags & SQLITE_FUNC_AFFINITY ){
+ const char *azAff[] = { "blob", "text", "numeric", "integer", "real" };
+ char aff;
+ assert( nFarg==1 );
+ aff = sqlite3ExprAffinity(pFarg->a[0].pExpr);
+ sqlite3VdbeLoadString(v, target,
+ aff ? azAff[aff-SQLITE_AFF_BLOB] : "none");
+ return target;
+ }
+#endif
+
for(i=0; ia[i].pExpr) ){
testcase( i==31 );
@@ -93403,9 +96556,21 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
if( !pColl ) pColl = db->pDfltColl;
sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ);
}
- sqlite3VdbeAddOp4(v, OP_Function0, constMask, r1, target,
- (char*)pDef, P4_FUNCDEF);
- sqlite3VdbeChangeP5(v, (u8)nFarg);
+#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
+ if( pDef->funcFlags & SQLITE_FUNC_OFFSET ){
+ Expr *pArg = pFarg->a[0].pExpr;
+ if( pArg->op==TK_COLUMN ){
+ sqlite3VdbeAddOp3(v, OP_Offset, pArg->iTable, pArg->iColumn, target);
+ }else{
+ sqlite3VdbeAddOp2(v, OP_Null, 0, target);
+ }
+ }else
+#endif
+ {
+ sqlite3VdbeAddOp4(v, pParse->iSelfTab ? OP_PureFunc0 : OP_Function0,
+ constMask, r1, target, (char*)pDef, P4_FUNCDEF);
+ sqlite3VdbeChangeP5(v, (u8)nFarg);
+ }
if( nFarg && constMask==0 ){
sqlite3ReleaseTempRange(pParse, r1, nFarg);
}
@@ -93425,9 +96590,17 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
break;
}
case TK_SELECT_COLUMN: {
+ int n;
if( pExpr->pLeft->iTable==0 ){
pExpr->pLeft->iTable = sqlite3CodeSubselect(pParse, pExpr->pLeft, 0, 0);
}
+ assert( pExpr->iTable==0 || pExpr->pLeft->op==TK_SELECT );
+ if( pExpr->iTable
+ && pExpr->iTable!=(n = sqlite3ExprVectorSize(pExpr->pLeft))
+ ){
+ sqlite3ErrorMsg(pParse, "%d columns assigned %d values",
+ pExpr->iTable, n);
+ }
return pExpr->pLeft->iTable + pExpr->iColumn;
}
case TK_IN: {
@@ -93526,6 +96699,17 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
break;
}
+ case TK_IF_NULL_ROW: {
+ int addrINR;
+ addrINR = sqlite3VdbeAddOp1(v, OP_IfNullRow, pExpr->iTable);
+ sqlite3ExprCachePush(pParse);
+ inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
+ sqlite3ExprCachePop(pParse);
+ sqlite3VdbeJumpHere(v, addrINR);
+ sqlite3VdbeChangeP3(v, addrINR, inReg);
+ break;
+ }
+
/*
** Form A:
** CASE x WHEN e1 THEN r1 WHEN e2 THEN r2 ... WHEN eN THEN rN ELSE y END
@@ -93645,24 +96829,40 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
/*
** Factor out the code of the given expression to initialization time.
+**
+** If regDest>=0 then the result is always stored in that register and the
+** result is not reusable. If regDest<0 then this routine is free to
+** store the value whereever it wants. The register where the expression
+** is stored is returned. When regDest<0, two identical expressions will
+** code to the same register.
*/
-SQLITE_PRIVATE void sqlite3ExprCodeAtInit(
+SQLITE_PRIVATE int sqlite3ExprCodeAtInit(
Parse *pParse, /* Parsing context */
Expr *pExpr, /* The expression to code when the VDBE initializes */
- int regDest, /* Store the value in this register */
- u8 reusable /* True if this expression is reusable */
+ int regDest /* Store the value in this register */
){
ExprList *p;
assert( ConstFactorOk(pParse) );
p = pParse->pConstExpr;
+ if( regDest<0 && p ){
+ struct ExprList_item *pItem;
+ int i;
+ for(pItem=p->a, i=p->nExpr; i>0; pItem++, i--){
+ if( pItem->reusable && sqlite3ExprCompare(0,pItem->pExpr,pExpr,-1)==0 ){
+ return pItem->u.iConstExprReg;
+ }
+ }
+ }
pExpr = sqlite3ExprDup(pParse->db, pExpr, 0);
p = sqlite3ExprListAppend(pParse, p, pExpr);
if( p ){
struct ExprList_item *pItem = &p->a[p->nExpr-1];
+ pItem->reusable = regDest<0;
+ if( regDest<0 ) regDest = ++pParse->nMem;
pItem->u.iConstExprReg = regDest;
- pItem->reusable = reusable;
}
pParse->pConstExpr = p;
+ return regDest;
}
/*
@@ -93685,19 +96885,8 @@ SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){
&& pExpr->op!=TK_REGISTER
&& sqlite3ExprIsConstantNotJoin(pExpr)
){
- ExprList *p = pParse->pConstExpr;
- int i;
*pReg = 0;
- if( p ){
- struct ExprList_item *pItem;
- for(pItem=p->a, i=p->nExpr; i>0; pItem++, i--){
- if( pItem->reusable && sqlite3ExprCompare(pItem->pExpr,pExpr,-1)==0 ){
- return pItem->u.iConstExprReg;
- }
- }
- }
- r2 = ++pParse->nMem;
- sqlite3ExprCodeAtInit(pParse, pExpr, r2, 1);
+ r2 = sqlite3ExprCodeAtInit(pParse, pExpr, -1);
}else{
int r1 = sqlite3GetTempReg(pParse);
r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
@@ -93751,7 +96940,7 @@ SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse *pParse, Expr *pExpr, int target){
*/
SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse *pParse, Expr *pExpr, int target){
if( pParse->okConstFactor && sqlite3ExprIsConstant(pExpr) ){
- sqlite3ExprCodeAtInit(pParse, pExpr, target, 0);
+ sqlite3ExprCodeAtInit(pParse, pExpr, target);
}else{
sqlite3ExprCode(pParse, pExpr, target);
}
@@ -93785,7 +96974,9 @@ SQLITE_PRIVATE void sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int targ
** Generate code that pushes the value of every element of the given
** expression list into a sequence of registers beginning at target.
**
-** Return the number of elements evaluated.
+** Return the number of elements evaluated. The number returned will
+** usually be pList->nExpr but might be reduced if SQLITE_ECEL_OMITREF
+** is defined.
**
** The SQLITE_ECEL_DUP flag prevents the arguments from being
** filled using OP_SCopy. OP_Copy must be used instead.
@@ -93796,6 +96987,8 @@ SQLITE_PRIVATE void sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int targ
** The SQLITE_ECEL_REF flag means that expressions in the list with
** ExprList.a[].u.x.iOrderByCol>0 have already been evaluated and stored
** in registers at srcReg, and so the value can be copied from there.
+** If SQLITE_ECEL_OMITREF is also set, then the values with u.x.iOrderByCol>0
+** are simply omitted rather than being copied from srcReg.
*/
SQLITE_PRIVATE int sqlite3ExprCodeExprList(
Parse *pParse, /* Parsing context */
@@ -93815,10 +97008,15 @@ SQLITE_PRIVATE int sqlite3ExprCodeExprList(
if( !ConstFactorOk(pParse) ) flags &= ~SQLITE_ECEL_FACTOR;
for(pItem=pList->a, i=0; ipExpr;
- if( (flags & SQLITE_ECEL_REF)!=0 && (j = pList->a[i].u.x.iOrderByCol)>0 ){
- sqlite3VdbeAddOp2(v, copyOp, j+srcReg-1, target+i);
+ if( (flags & SQLITE_ECEL_REF)!=0 && (j = pItem->u.x.iOrderByCol)>0 ){
+ if( flags & SQLITE_ECEL_OMITREF ){
+ i--;
+ n--;
+ }else{
+ sqlite3VdbeAddOp2(v, copyOp, j+srcReg-1, target+i);
+ }
}else if( (flags & SQLITE_ECEL_FACTOR)!=0 && sqlite3ExprIsConstant(pExpr) ){
- sqlite3ExprCodeAtInit(pParse, pExpr, target+i, 0);
+ sqlite3ExprCodeAtInit(pParse, pExpr, target+i);
}else{
int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target+i);
if( inReg!=target+i ){
@@ -93891,6 +97089,11 @@ static void exprCodeBetween(
if( xJump ){
xJump(pParse, &exprAnd, dest, jumpIfNull);
}else{
+ /* Mark the expression is being from the ON or USING clause of a join
+ ** so that the sqlite3ExprCodeTarget() routine will not attempt to move
+ ** it into the Parse.pConstExpr list. We should use a new bit for this,
+ ** for clarity, but we are out of bits in the Expr.flags field so we
+ ** have to reuse the EP_FromJoin bit. Bummer. */
exprX.flags |= EP_FromJoin;
sqlite3ExprCodeTarget(pParse, &exprAnd, dest);
}
@@ -94204,6 +97407,41 @@ SQLITE_PRIVATE void sqlite3ExprIfFalseDup(Parse *pParse, Expr *pExpr, int dest,i
sqlite3ExprDelete(db, pCopy);
}
+/*
+** Expression pVar is guaranteed to be an SQL variable. pExpr may be any
+** type of expression.
+**
+** If pExpr is a simple SQL value - an integer, real, string, blob
+** or NULL value - then the VDBE currently being prepared is configured
+** to re-prepare each time a new value is bound to variable pVar.
+**
+** Additionally, if pExpr is a simple SQL value and the value is the
+** same as that currently bound to variable pVar, non-zero is returned.
+** Otherwise, if the values are not the same or if pExpr is not a simple
+** SQL value, zero is returned.
+*/
+static int exprCompareVariable(Parse *pParse, Expr *pVar, Expr *pExpr){
+ int res = 0;
+ int iVar;
+ sqlite3_value *pL, *pR = 0;
+
+ sqlite3ValueFromExpr(pParse->db, pExpr, SQLITE_UTF8, SQLITE_AFF_BLOB, &pR);
+ if( pR ){
+ iVar = pVar->iColumn;
+ sqlite3VdbeSetVarmask(pParse->pVdbe, iVar);
+ pL = sqlite3VdbeGetBoundValue(pParse->pReprepare, iVar, SQLITE_AFF_BLOB);
+ if( pL ){
+ if( sqlite3_value_type(pL)==SQLITE_TEXT ){
+ sqlite3_value_text(pL); /* Make sure the encoding is UTF-8 */
+ }
+ res = 0==sqlite3MemCompare(pL, pR, 0);
+ }
+ sqlite3ValueFree(pR);
+ sqlite3ValueFree(pL);
+ }
+
+ return res;
+}
/*
** Do a deep comparison of two expression trees. Return 0 if the two
@@ -94226,12 +97464,22 @@ SQLITE_PRIVATE void sqlite3ExprIfFalseDup(Parse *pParse, Expr *pExpr, int dest,i
** this routine is used, it does not hurt to get an extra 2 - that
** just might result in some slightly slower code. But returning
** an incorrect 0 or 1 could lead to a malfunction.
+**
+** If pParse is not NULL then TK_VARIABLE terms in pA with bindings in
+** pParse->pReprepare can be matched against literals in pB. The
+** pParse->pVdbe->expmask bitmask is updated for each variable referenced.
+** If pParse is NULL (the normal case) then any TK_VARIABLE term in
+** Argument pParse should normally be NULL. If it is not NULL and pA or
+** pB causes a return value of 2.
*/
-SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){
+SQLITE_PRIVATE int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){
u32 combinedFlags;
if( pA==0 || pB==0 ){
return pB==pA ? 0 : 2;
}
+ if( pParse && pA->op==TK_VARIABLE && exprCompareVariable(pParse, pA, pB) ){
+ return 0;
+ }
combinedFlags = pA->flags | pB->flags;
if( combinedFlags & EP_IntValue ){
if( (pA->flags&pB->flags&EP_IntValue)!=0 && pA->u.iValue==pB->u.iValue ){
@@ -94240,10 +97488,10 @@ SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){
return 2;
}
if( pA->op!=pB->op ){
- if( pA->op==TK_COLLATE && sqlite3ExprCompare(pA->pLeft, pB, iTab)<2 ){
+ if( pA->op==TK_COLLATE && sqlite3ExprCompare(pParse, pA->pLeft,pB,iTab)<2 ){
return 1;
}
- if( pB->op==TK_COLLATE && sqlite3ExprCompare(pA, pB->pLeft, iTab)<2 ){
+ if( pB->op==TK_COLLATE && sqlite3ExprCompare(pParse, pA,pB->pLeft,iTab)<2 ){
return 1;
}
return 2;
@@ -94258,8 +97506,8 @@ SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){
if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
if( ALWAYS((combinedFlags & EP_TokenOnly)==0) ){
if( combinedFlags & EP_xIsSelect ) return 2;
- if( sqlite3ExprCompare(pA->pLeft, pB->pLeft, iTab) ) return 2;
- if( sqlite3ExprCompare(pA->pRight, pB->pRight, iTab) ) return 2;
+ if( sqlite3ExprCompare(pParse, pA->pLeft, pB->pLeft, iTab) ) return 2;
+ if( sqlite3ExprCompare(pParse, pA->pRight, pB->pRight, iTab) ) return 2;
if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2;
if( ALWAYS((combinedFlags & EP_Reduced)==0) && pA->op!=TK_STRING ){
if( pA->iColumn!=pB->iColumn ) return 2;
@@ -94294,11 +97542,22 @@ SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList *pA, ExprList *pB, int iTab){
Expr *pExprA = pA->a[i].pExpr;
Expr *pExprB = pB->a[i].pExpr;
if( pA->a[i].sortOrder!=pB->a[i].sortOrder ) return 1;
- if( sqlite3ExprCompare(pExprA, pExprB, iTab) ) return 1;
+ if( sqlite3ExprCompare(0, pExprA, pExprB, iTab) ) return 1;
}
return 0;
}
+/*
+** Like sqlite3ExprCompare() except COLLATE operators at the top-level
+** are ignored.
+*/
+SQLITE_PRIVATE int sqlite3ExprCompareSkip(Expr *pA, Expr *pB, int iTab){
+ return sqlite3ExprCompare(0,
+ sqlite3ExprSkipCollate(pA),
+ sqlite3ExprSkipCollate(pB),
+ iTab);
+}
+
/*
** Return true if we can prove the pE2 will always be true if pE1 is
** true. Return false if we cannot complete the proof or if pE2 might
@@ -94315,25 +97574,29 @@ SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList *pA, ExprList *pB, int iTab){
** When comparing TK_COLUMN nodes between pE1 and pE2, if pE2 has
** Expr.iTable<0 then assume a table number given by iTab.
**
+** If pParse is not NULL, then the values of bound variables in pE1 are
+** compared against literal values in pE2 and pParse->pVdbe->expmask is
+** modified to record which bound variables are referenced. If pParse
+** is NULL, then false will be returned if pE1 contains any bound variables.
+**
** When in doubt, return false. Returning true might give a performance
** improvement. Returning false might cause a performance reduction, but
** it will always give the correct answer and is hence always safe.
*/
-SQLITE_PRIVATE int sqlite3ExprImpliesExpr(Expr *pE1, Expr *pE2, int iTab){
- if( sqlite3ExprCompare(pE1, pE2, iTab)==0 ){
+SQLITE_PRIVATE int sqlite3ExprImpliesExpr(Parse *pParse, Expr *pE1, Expr *pE2, int iTab){
+ if( sqlite3ExprCompare(pParse, pE1, pE2, iTab)==0 ){
return 1;
}
if( pE2->op==TK_OR
- && (sqlite3ExprImpliesExpr(pE1, pE2->pLeft, iTab)
- || sqlite3ExprImpliesExpr(pE1, pE2->pRight, iTab) )
+ && (sqlite3ExprImpliesExpr(pParse, pE1, pE2->pLeft, iTab)
+ || sqlite3ExprImpliesExpr(pParse, pE1, pE2->pRight, iTab) )
){
return 1;
}
- if( pE2->op==TK_NOTNULL
- && sqlite3ExprCompare(pE1->pLeft, pE2->pLeft, iTab)==0
- && (pE1->op!=TK_ISNULL && pE1->op!=TK_IS)
- ){
- return 1;
+ if( pE2->op==TK_NOTNULL && pE1->op!=TK_ISNULL && pE1->op!=TK_IS ){
+ Expr *pX = sqlite3ExprSkipCollate(pE1->pLeft);
+ testcase( pX!=pE1->pLeft );
+ if( sqlite3ExprCompare(pParse, pX, pE2->pLeft, iTab)==0 ) return 1;
}
return 0;
}
@@ -94441,8 +97704,8 @@ SQLITE_PRIVATE int sqlite3FunctionUsesThisSrc(Expr *pExpr, SrcList *pSrcList){
Walker w;
struct SrcCount cnt;
assert( pExpr->op==TK_AGG_FUNCTION );
- memset(&w, 0, sizeof(w));
w.xExprCallback = exprSrcCount;
+ w.xSelectCallback = 0;
w.u.pSrcCount = &cnt;
cnt.pSrc = pSrcList;
cnt.nThis = 0;
@@ -94574,7 +97837,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
*/
struct AggInfo_func *pItem = pAggInfo->aFunc;
for(i=0; inFunc; i++, pItem++){
- if( sqlite3ExprCompare(pItem->pExpr, pExpr, -1)==0 ){
+ if( sqlite3ExprCompare(0, pItem->pExpr, pExpr, -1)==0 ){
break;
}
}
@@ -94614,10 +97877,14 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
return WRC_Continue;
}
static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){
- UNUSED_PARAMETER(pWalker);
UNUSED_PARAMETER(pSelect);
+ pWalker->walkerDepth++;
return WRC_Continue;
}
+static void analyzeAggregatesInSelectEnd(Walker *pWalker, Select *pSelect){
+ UNUSED_PARAMETER(pSelect);
+ pWalker->walkerDepth--;
+}
/*
** Analyze the pExpr expression looking for aggregate functions and
@@ -94630,9 +97897,10 @@ static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){
*/
SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){
Walker w;
- memset(&w, 0, sizeof(w));
w.xExprCallback = analyzeAggregate;
w.xSelectCallback = analyzeAggregatesInSelect;
+ w.xSelectCallback2 = analyzeAggregatesInSelectEnd;
+ w.walkerDepth = 0;
w.u.pNC = pNC;
assert( pNC->pSrcList!=0 );
sqlite3WalkExpr(&w, pExpr);
@@ -94733,8 +98001,8 @@ SQLITE_PRIVATE void sqlite3ClearTempRegCache(Parse *pParse){
SQLITE_PRIVATE int sqlite3NoTempsInRange(Parse *pParse, int iFirst, int iLast){
int i;
if( pParse->nRangeReg>0
- && pParse->iRangeReg+pParse->nRangeRegiRangeReg>=iFirst
+ && pParse->iRangeReg+pParse->nRangeReg > iFirst
+ && pParse->iRangeReg <= iLast
){
return 0;
}
@@ -95126,7 +98394,7 @@ static void reloadTableSchema(Parse *pParse, Table *pTab, const char *zName){
** Or, if zName is not a system table, zero is returned.
*/
static int isSystemTable(Parse *pParse, const char *zName){
- if( sqlite3Strlen30(zName)>6 && 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){
+ if( 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){
sqlite3ErrorMsg(pParse, "table %s may not be altered", zName);
return 1;
}
@@ -95154,9 +98422,9 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable(
char *zWhere = 0; /* Where clause to locate temp triggers */
#endif
VTable *pVTab = 0; /* Non-zero if this is a v-tab with an xRename() */
- int savedDbFlags; /* Saved value of db->flags */
+ u32 savedDbFlags; /* Saved value of db->mDbFlags */
- savedDbFlags = db->flags;
+ savedDbFlags = db->mDbFlags;
if( NEVER(db->mallocFailed) ) goto exit_rename_table;
assert( pSrc->nSrc==1 );
assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
@@ -95165,7 +98433,7 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable(
if( !pTab ) goto exit_rename_table;
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
zDb = db->aDb[iDb].zDbSName;
- db->flags |= SQLITE_PreferBuiltin;
+ db->mDbFlags |= DBFLAG_PreferBuiltin;
/* Get a NULL terminated version of the new table name. */
zName = sqlite3NameFromToken(db, pName);
@@ -95255,7 +98523,7 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable(
sqlite3NestedParse(pParse,
"UPDATE \"%w\".%s SET "
"sql = sqlite_rename_parent(sql, %Q, %Q) "
- "WHERE %s;", zDb, SCHEMA_TABLE(iDb), zTabName, zName, zWhere);
+ "WHERE %s;", zDb, MASTER_NAME, zTabName, zName, zWhere);
sqlite3DbFree(db, zWhere);
}
}
@@ -95279,7 +98547,7 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable(
"ELSE name END "
"WHERE tbl_name=%Q COLLATE nocase AND "
"(type='table' OR type='index' OR type='trigger');",
- zDb, SCHEMA_TABLE(iDb), zName, zName, zName,
+ zDb, MASTER_NAME, zName, zName, zName,
#ifndef SQLITE_OMIT_TRIGGER
zName,
#endif
@@ -95330,7 +98598,7 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable(
exit_rename_table:
sqlite3SrcListDelete(db, pSrc);
sqlite3DbFree(db, zName);
- db->flags = savedDbFlags;
+ db->mDbFlags = savedDbFlags;
}
/*
@@ -95431,20 +98699,20 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
zCol = sqlite3DbStrNDup(db, (char*)pColDef->z, pColDef->n);
if( zCol ){
char *zEnd = &zCol[pColDef->n-1];
- int savedDbFlags = db->flags;
+ u32 savedDbFlags = db->mDbFlags;
while( zEnd>zCol && (*zEnd==';' || sqlite3Isspace(*zEnd)) ){
*zEnd-- = '\0';
}
- db->flags |= SQLITE_PreferBuiltin;
+ db->mDbFlags |= DBFLAG_PreferBuiltin;
sqlite3NestedParse(pParse,
"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,
+ zDb, MASTER_NAME, pNew->addColOffset, zCol, pNew->addColOffset+1,
zTab
);
sqlite3DbFree(db, zCol);
- db->flags = savedDbFlags;
+ db->mDbFlags = savedDbFlags;
}
/* Make sure the schema version is at least 3. But do not upgrade
@@ -95524,7 +98792,7 @@ SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
pNew = (Table*)sqlite3DbMallocZero(db, sizeof(Table));
if( !pNew ) goto exit_begin_add_column;
pParse->pNewTable = pNew;
- pNew->nRef = 1;
+ pNew->nTabRef = 1;
pNew->nCol = pTab->nCol;
assert( pNew->nCol>0 );
nAlloc = (((pNew->nCol-1)/8)*8)+8;
@@ -95544,7 +98812,7 @@ SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
}
pNew->pSchema = db->aDb[iDb].pSchema;
pNew->addColOffset = pTab->addColOffset;
- pNew->nRef = 1;
+ pNew->nTabRef = 1;
/* Begin a transaction and increment the schema cookie. */
sqlite3BeginWriteOperation(pParse, 0, iDb);
@@ -95796,6 +99064,10 @@ static void openStatTable(
"DELETE FROM %Q.%s WHERE %s=%Q",
pDb->zDbSName, zTab, zWhereType, zWhere
);
+#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
+ }else if( db->xPreUpdateCallback ){
+ sqlite3NestedParse(pParse, "DELETE FROM %Q.%s", pDb->zDbSName, zTab);
+#endif
}else{
/* The sqlite_stat[134] table already exists. Delete all rows. */
sqlite3VdbeAddOp2(v, OP_Clear, aRoot[i], iDb);
@@ -95852,6 +99124,7 @@ struct Stat4Accum {
Stat4Sample *aBest; /* Array of nCol best samples */
int iMin; /* Index in a[] of entry with minimum score */
int nSample; /* Current number of samples */
+ int nMaxEqZero; /* Max leading 0 in anEq[] for any a[] entry */
int iGet; /* Index of current sample accessed by stat_get() */
Stat4Sample *a; /* Array of mxSample Stat4Sample objects */
sqlite3 *db; /* Database connection, for malloc() */
@@ -96116,6 +99389,13 @@ static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){
assert( IsStat4 || nEqZero==0 );
#ifdef SQLITE_ENABLE_STAT4
+ /* Stat4Accum.nMaxEqZero is set to the maximum number of leading 0
+ ** values in the anEq[] array of any sample in Stat4Accum.a[]. In
+ ** other words, if nMaxEqZero is n, then it is guaranteed that there
+ ** are no samples with Stat4Sample.anEq[m]==0 for (m>=n). */
+ if( nEqZero>p->nMaxEqZero ){
+ p->nMaxEqZero = nEqZero;
+ }
if( pNew->isPSample==0 ){
Stat4Sample *pUpgrade = 0;
assert( pNew->anEq[pNew->iCol]>0 );
@@ -96213,12 +99493,22 @@ static void samplePushPrevious(Stat4Accum *p, int iChng){
}
}
- /* Update the anEq[] fields of any samples already collected. */
+ /* Check that no sample contains an anEq[] entry with an index of
+ ** p->nMaxEqZero or greater set to zero. */
for(i=p->nSample-1; i>=0; i--){
int j;
- for(j=iChng; jnCol; j++){
- if( p->a[i].anEq[j]==0 ) p->a[i].anEq[j] = p->current.anEq[j];
+ for(j=p->nMaxEqZero; jnCol; j++) assert( p->a[i].anEq[j]>0 );
+ }
+
+ /* Update the anEq[] fields of any samples already collected. */
+ if( iChngnMaxEqZero ){
+ for(i=p->nSample-1; i>=0; i--){
+ int j;
+ for(j=iChng; jnCol; j++){
+ if( p->a[i].anEq[j]==0 ) p->a[i].anEq[j] = p->current.anEq[j];
+ }
}
+ p->nMaxEqZero = iChng;
}
#endif
@@ -96359,6 +99649,12 @@ static const FuncDef statPushFuncdef = {
** The content to returned is determined by the parameter J
** which is one of the STAT_GET_xxxx values defined above.
**
+** The stat_get(P,J) function is not available to generic SQL. It is
+** inserted as part of a manually constructed bytecode program. (See
+** the callStatGet() routine below.) It is guaranteed that the P
+** parameter will always be a poiner to a Stat4Accum object, never a
+** NULL.
+**
** If neither STAT3 nor STAT4 are enabled, then J is always
** STAT_GET_STAT1 and is hence omitted and this routine becomes
** a one-parameter function, stat_get(P), that always returns the
@@ -96536,6 +99832,9 @@ static void analyzeOneTable(
int regIdxname = iMem++; /* Register containing index name */
int regStat1 = iMem++; /* Value for the stat column of sqlite_stat1 */
int regPrev = iMem; /* MUST BE LAST (see below) */
+#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
+ Table *pStat1 = 0;
+#endif
pParse->nMem = MAX(pParse->nMem, iMem);
v = sqlite3GetVdbe(pParse);
@@ -96561,6 +99860,18 @@ static void analyzeOneTable(
}
#endif
+#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
+ if( db->xPreUpdateCallback ){
+ pStat1 = (Table*)sqlite3DbMallocZero(db, sizeof(Table) + 13);
+ if( pStat1==0 ) return;
+ pStat1->zName = (char*)&pStat1[1];
+ memcpy(pStat1->zName, "sqlite_stat1", 13);
+ pStat1->nCol = 3;
+ pStat1->iPKey = -1;
+ sqlite3VdbeAddOp4(pParse->pVdbe, OP_Noop, 0, 0, 0,(char*)pStat1,P4_DYNBLOB);
+ }
+#endif
+
/* Establish a read-lock on the table at the shared-cache level.
** Open a read-only cursor on the table. Also allocate a cursor number
** to use for scanning indexes (iIdxCur). No index cursor is opened at
@@ -96742,7 +100053,7 @@ static void analyzeOneTable(
regKey = sqlite3GetTempRange(pParse, pPk->nKeyCol);
for(j=0; jnKeyCol; j++){
k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[j]);
- assert( k>=0 && knCol );
+ assert( k>=0 && knColumn );
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, regKey+j);
VdbeComment((v, "%s", pTab->aCol[pPk->aiColumn[j]].zName));
}
@@ -96762,6 +100073,9 @@ static void analyzeOneTable(
sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "BBB", 0);
sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regTemp, regNewRowid);
+#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
+ sqlite3VdbeChangeP4(v, -1, (char*)pStat1, P4_TABLE);
+#endif
sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
/* Add the entries to the stat3 or stat4 table. */
@@ -96825,6 +100139,9 @@ static void analyzeOneTable(
sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regTemp, regNewRowid);
sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
+#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
+ sqlite3VdbeChangeP4(v, -1, (char*)pStat1, P4_TABLE);
+#endif
sqlite3VdbeJumpHere(v, jZeroRows);
}
}
@@ -96926,27 +100243,14 @@ SQLITE_PRIVATE void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){
if( i==1 ) continue; /* Do not analyze the TEMP database */
analyzeDatabase(pParse, i);
}
- }else if( pName2->n==0 ){
- /* Form 2: Analyze the database or table named */
- iDb = sqlite3FindDb(db, pName1);
- if( iDb>=0 ){
- analyzeDatabase(pParse, iDb);
- }else{
- z = sqlite3NameFromToken(db, pName1);
- if( z ){
- if( (pIdx = sqlite3FindIndex(db, z, 0))!=0 ){
- analyzeTable(pParse, pIdx->pTable, pIdx);
- }else if( (pTab = sqlite3LocateTable(pParse, 0, z, 0))!=0 ){
- analyzeTable(pParse, pTab, 0);
- }
- sqlite3DbFree(db, z);
- }
- }
+ }else if( pName2->n==0 && (iDb = sqlite3FindDb(db, pName1))>=0 ){
+ /* Analyze the schema named as the argument */
+ analyzeDatabase(pParse, iDb);
}else{
- /* Form 3: Analyze the fully qualified table name */
+ /* Form 3: Analyze the table or index named as an argument */
iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pTableName);
if( iDb>=0 ){
- zDb = db->aDb[iDb].zDbSName;
+ zDb = pName2->n ? db->aDb[iDb].zDbSName : 0;
z = sqlite3NameFromToken(db, pTableName);
if( z ){
if( (pIdx = sqlite3FindIndex(db, z, zDb))!=0 ){
@@ -96956,10 +100260,11 @@ SQLITE_PRIVATE void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){
}
sqlite3DbFree(db, z);
}
- }
+ }
+ }
+ if( db->nSqlExec==0 && (v = sqlite3GetVdbe(pParse))!=0 ){
+ sqlite3VdbeAddOp0(v, OP_Expire);
}
- v = sqlite3GetVdbe(pParse);
- if( v ) sqlite3VdbeAddOp0(v, OP_Expire);
}
/*
@@ -97088,7 +100393,11 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
#endif
pIndex->bUnordered = 0;
decodeIntArray((char*)z, nCol, aiRowEst, pIndex->aiRowLogEst, pIndex);
- if( pIndex->pPartIdxWhere==0 ) pTable->nRowLogEst = pIndex->aiRowLogEst[0];
+ pIndex->hasStat1 = 1;
+ if( pIndex->pPartIdxWhere==0 ){
+ pTable->nRowLogEst = pIndex->aiRowLogEst[0];
+ pTable->tabFlags |= TF_HasStat1;
+ }
}else{
Index fakeIdx;
fakeIdx.szIdxRow = pTable->szTabRow;
@@ -97097,6 +100406,7 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
#endif
decodeIntArray((char*)z, 1, 0, &pTable->nRowLogEst, &fakeIdx);
pTable->szTabRow = fakeIdx.szIdxRow;
+ pTable->tabFlags |= TF_HasStat1;
}
return 0;
@@ -97177,7 +100487,7 @@ static void initAvgEq(Index *pIdx){
}
}
- if( nDist100>nSum100 ){
+ if( nDist100>nSum100 && sumEqp, sqlite3_column_blob(pStmt, 4), pSample->n);
+ if( pSample->n ){
+ memcpy(pSample->p, sqlite3_column_blob(pStmt, 4), pSample->n);
+ }
pIdx->nSample++;
}
rc = sqlite3_finalize(pStmt);
@@ -97389,15 +100701,20 @@ SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
HashElem *i;
char *zSql;
int rc = SQLITE_OK;
+ Schema *pSchema = db->aDb[iDb].pSchema;
assert( iDb>=0 && iDbnDb );
assert( db->aDb[iDb].pBt!=0 );
/* Clear any prior statistics */
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
- for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){
+ for(i=sqliteHashFirst(&pSchema->tblHash); i; i=sqliteHashNext(i)){
+ Table *pTab = sqliteHashData(i);
+ pTab->tabFlags &= ~TF_HasStat1;
+ }
+ for(i=sqliteHashFirst(&pSchema->idxHash); i; i=sqliteHashNext(i)){
Index *pIdx = sqliteHashData(i);
- pIdx->aiRowLogEst[0] = 0;
+ pIdx->hasStat1 = 0;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
sqlite3DeleteIndexSamples(db, pIdx);
pIdx->aSample = 0;
@@ -97420,9 +100737,9 @@ SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
/* Set appropriate defaults on all indexes not in the sqlite_stat1 table */
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
- for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){
+ for(i=sqliteHashFirst(&pSchema->idxHash); i; i=sqliteHashNext(i)){
Index *pIdx = sqliteHashData(i);
- if( pIdx->aiRowLogEst[0]==0 ) sqlite3DefaultRowEst(pIdx);
+ if( !pIdx->hasStat1 ) sqlite3DefaultRowEst(pIdx);
}
/* Load the statistics from the sqlite_stat4 table. */
@@ -97432,7 +100749,7 @@ SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
rc = loadStat4(db, sInfo.zDatabase);
db->lookaside.bDisable--;
}
- for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){
+ for(i=sqliteHashFirst(&pSchema->idxHash); i; i=sqliteHashNext(i)){
Index *pIdx = sqliteHashData(i);
sqlite3_free(pIdx->aiRowEst);
pIdx->aiRowEst = 0;
@@ -97521,7 +100838,8 @@ static void attachFunc(
char *zPath = 0;
char *zErr = 0;
unsigned int flags;
- Db *aNew;
+ Db *aNew; /* New array of Db pointers */
+ Db *pNew; /* Db object for the newly attached database */
char *zErrDyn = 0;
sqlite3_vfs *pVfs;
@@ -97544,10 +100862,6 @@ static void attachFunc(
);
goto attach_error;
}
- if( !db->autoCommit ){
- zErrDyn = sqlite3MPrintf(db, "cannot ATTACH database within transaction");
- goto attach_error;
- }
for(i=0; inDb; i++){
char *z = db->aDb[i].zDbSName;
assert( z && zName );
@@ -97569,8 +100883,8 @@ static void attachFunc(
if( aNew==0 ) return;
}
db->aDb = aNew;
- aNew = &db->aDb[db->nDb];
- memset(aNew, 0, sizeof(*aNew));
+ pNew = &db->aDb[db->nDb];
+ memset(pNew, 0, sizeof(*pNew));
/* Open the database file. If the btree is successfully opened, use
** it to obtain the database schema. At this point the schema may
@@ -97586,36 +100900,37 @@ static void attachFunc(
}
assert( pVfs );
flags |= SQLITE_OPEN_MAIN_DB;
- rc = sqlite3BtreeOpen(pVfs, zPath, db, &aNew->pBt, 0, flags);
+ rc = sqlite3BtreeOpen(pVfs, zPath, db, &pNew->pBt, 0, flags);
sqlite3_free( zPath );
db->nDb++;
+ db->skipBtreeMutex = 0;
if( rc==SQLITE_CONSTRAINT ){
rc = SQLITE_ERROR;
zErrDyn = sqlite3MPrintf(db, "database is already attached");
}else if( rc==SQLITE_OK ){
Pager *pPager;
- aNew->pSchema = sqlite3SchemaGet(db, aNew->pBt);
- if( !aNew->pSchema ){
+ pNew->pSchema = sqlite3SchemaGet(db, pNew->pBt);
+ if( !pNew->pSchema ){
rc = SQLITE_NOMEM_BKPT;
- }else if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){
+ }else if( pNew->pSchema->file_format && pNew->pSchema->enc!=ENC(db) ){
zErrDyn = sqlite3MPrintf(db,
"attached databases must use the same text encoding as main database");
rc = SQLITE_ERROR;
}
- sqlite3BtreeEnter(aNew->pBt);
- pPager = sqlite3BtreePager(aNew->pBt);
+ sqlite3BtreeEnter(pNew->pBt);
+ pPager = sqlite3BtreePager(pNew->pBt);
sqlite3PagerLockingMode(pPager, db->dfltLockMode);
- sqlite3BtreeSecureDelete(aNew->pBt,
+ sqlite3BtreeSecureDelete(pNew->pBt,
sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) );
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
- sqlite3BtreeSetPagerFlags(aNew->pBt,
+ sqlite3BtreeSetPagerFlags(pNew->pBt,
PAGER_SYNCHRONOUS_FULL | (db->flags & PAGER_FLAGS_MASK));
#endif
- sqlite3BtreeLeave(aNew->pBt);
+ sqlite3BtreeLeave(pNew->pBt);
}
- aNew->safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1;
- aNew->zDbSName = sqlite3DbStrDup(db, zName);
- if( rc==SQLITE_OK && aNew->zDbSName==0 ){
+ pNew->safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1;
+ pNew->zDbSName = sqlite3DbStrDup(db, zName);
+ if( rc==SQLITE_OK && pNew->zDbSName==0 ){
rc = SQLITE_NOMEM_BKPT;
}
@@ -97738,11 +101053,6 @@ static void detachFunc(
sqlite3_snprintf(sizeof(zErr),zErr, "cannot detach database %s", zName);
goto detach_error;
}
- if( !db->autoCommit ){
- sqlite3_snprintf(sizeof(zErr), zErr,
- "cannot DETACH database within transaction");
- goto detach_error;
- }
if( sqlite3BtreeIsInReadTrans(pDb->pBt) || sqlite3BtreeIsInBackup(pDb->pBt) ){
sqlite3_snprintf(sizeof(zErr),zErr, "database %s is locked", zName);
goto detach_error;
@@ -97963,9 +101273,6 @@ SQLITE_PRIVATE int sqlite3FixSelect(
if( sqlite3FixExpr(pFix, pSelect->pLimit) ){
return 1;
}
- if( sqlite3FixExpr(pFix, pSelect->pOffset) ){
- return 1;
- }
pSelect = pSelect->pPrior;
}
return 0;
@@ -98155,11 +101462,9 @@ SQLITE_PRIVATE int sqlite3AuthReadCol(
#endif
);
if( rc==SQLITE_DENY ){
- if( db->nDb>2 || iDb!=0 ){
- sqlite3ErrorMsg(pParse, "access to %s.%s.%s is prohibited",zDb,zTab,zCol);
- }else{
- sqlite3ErrorMsg(pParse, "access to %s.%s is prohibited", zTab, zCol);
- }
+ char *z = sqlite3_mprintf("%s.%s", zTab, zCol);
+ if( db->nDb>2 || iDb!=0 ) z = sqlite3_mprintf("%s.%z", zDb, z);
+ sqlite3ErrorMsg(pParse, "access to %z is prohibited", z);
pParse->rc = SQLITE_AUTH;
}else if( rc!=SQLITE_IGNORE && rc!=SQLITE_OK ){
sqliteAuthBadReturnCode(pParse);
@@ -98253,6 +101558,18 @@ SQLITE_PRIVATE int sqlite3AuthCheck(
if( db->xAuth==0 ){
return SQLITE_OK;
}
+
+ /* EVIDENCE-OF: R-43249-19882 The third through sixth parameters to the
+ ** callback are either NULL pointers or zero-terminated strings that
+ ** contain additional details about the action to be authorized.
+ **
+ ** The following testcase() macros show that any of the 3rd through 6th
+ ** parameters can be either NULL or a string. */
+ testcase( zArg1==0 );
+ testcase( zArg2==0 );
+ testcase( zArg3==0 );
+ testcase( pParse->zAuthContext==0 );
+
rc = db->xAuth(db->pAuthArg, code, zArg1, zArg2, zArg3, pParse->zAuthContext
#ifdef SQLITE_USER_AUTHENTICATION
,db->auth.zAuthUser
@@ -98331,10 +101648,10 @@ SQLITE_PRIVATE void sqlite3AuthContextPop(AuthContext *pContext){
** codeTableLocks() functions.
*/
struct TableLock {
- int iDb; /* The database containing the table to be locked */
- int iTab; /* The root page of the table to be locked */
- u8 isWriteLock; /* True for write lock. False for a read lock */
- const char *zName; /* Name of the table */
+ int iDb; /* The database containing the table to be locked */
+ int iTab; /* The root page of the table to be locked */
+ u8 isWriteLock; /* True for write lock. False for a read lock */
+ const char *zLockName; /* Name of the table */
};
/*
@@ -98360,6 +101677,8 @@ SQLITE_PRIVATE void sqlite3TableLock(
TableLock *p;
assert( iDb>=0 );
+ if( iDb==1 ) return;
+ if( !sqlite3BtreeSharable(pParse->db->aDb[iDb].pBt) ) return;
for(i=0; inTableLock; i++){
p = &pToplevel->aTableLock[i];
if( p->iDb==iDb && p->iTab==iTab ){
@@ -98376,7 +101695,7 @@ SQLITE_PRIVATE void sqlite3TableLock(
p->iDb = iDb;
p->iTab = iTab;
p->isWriteLock = isWriteLock;
- p->zName = zName;
+ p->zLockName = zName;
}else{
pToplevel->nTableLock = 0;
sqlite3OomFault(pToplevel->db);
@@ -98398,7 +101717,7 @@ static void codeTableLocks(Parse *pParse){
TableLock *p = &pParse->aTableLock[i];
int p1 = p->iDb;
sqlite3VdbeAddOp4(pVdbe, OP_TableLock, p1, p->iTab, p->isWriteLock,
- p->zName, P4_STATIC);
+ p->zLockName, P4_STATIC);
}
}
#else
@@ -98607,15 +101926,22 @@ SQLITE_PRIVATE Table *sqlite3FindTable(sqlite3 *db, const char *zName, const cha
return 0;
}
#endif
- for(i=OMIT_TEMPDB; inDb; i++){
- int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
- if( zDatabase==0 || sqlite3StrICmp(zDatabase, db->aDb[j].zDbSName)==0 ){
- assert( sqlite3SchemaMutexHeld(db, j, 0) );
- p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName);
- if( p ) break;
+ while(1){
+ for(i=OMIT_TEMPDB; inDb; i++){
+ int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
+ if( zDatabase==0 || sqlite3StrICmp(zDatabase, db->aDb[j].zDbSName)==0 ){
+ assert( sqlite3SchemaMutexHeld(db, j, 0) );
+ p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName);
+ if( p ) return p;
+ }
}
+ /* Not found. If the name we were looking for was temp.sqlite_master
+ ** then change the name to sqlite_temp_master and try again. */
+ if( sqlite3StrICmp(zName, MASTER_NAME)!=0 ) break;
+ if( sqlite3_stricmp(zDatabase, db->aDb[1].zDbSName)!=0 ) break;
+ zName = TEMP_MASTER_NAME;
}
- return p;
+ return 0;
}
/*
@@ -98651,6 +101977,9 @@ SQLITE_PRIVATE Table *sqlite3LocateTable(
** CREATE, then check to see if it is the name of an virtual table that
** can be an eponymous virtual table. */
Module *pMod = (Module*)sqlite3HashFind(&pParse->db->aModule, zName);
+ if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){
+ pMod = sqlite3PragmaVtabRegister(pParse->db, zName);
+ }
if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){
return pMod->pEpoTab;
}
@@ -98768,7 +102097,7 @@ SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char
}
freeIndex(db, pIndex);
}
- db->flags |= SQLITE_InternChanges;
+ db->mDbFlags |= DBFLAG_SchemaChange;
}
/*
@@ -98803,28 +102132,26 @@ SQLITE_PRIVATE void sqlite3CollapseDatabaseArray(sqlite3 *db){
/*
** Reset the schema for the database at index iDb. Also reset the
-** TEMP schema.
+** TEMP schema. The reset is deferred if db->nSchemaLock is not zero.
+** Deferred resets may be run by calling with iDb<0.
*/
SQLITE_PRIVATE void sqlite3ResetOneSchema(sqlite3 *db, int iDb){
- Db *pDb;
+ int i;
assert( iDbnDb );
- /* Case 1: Reset the single schema identified by iDb */
- pDb = &db->aDb[iDb];
- assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
- assert( pDb->pSchema!=0 );
- sqlite3SchemaClear(pDb->pSchema);
+ if( iDb>=0 ){
+ assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
+ DbSetProperty(db, iDb, DB_ResetWanted);
+ DbSetProperty(db, 1, DB_ResetWanted);
+ }
- /* If any database other than TEMP is reset, then also reset TEMP
- ** since TEMP might be holding triggers that reference tables in the
- ** other database.
- */
- if( iDb!=1 ){
- pDb = &db->aDb[1];
- assert( pDb->pSchema!=0 );
- sqlite3SchemaClear(pDb->pSchema);
+ if( db->nSchemaLock==0 ){
+ for(i=0; inDb; i++){
+ if( DbHasProperty(db, i, DB_ResetWanted) ){
+ sqlite3SchemaClear(db->aDb[i].pSchema);
+ }
+ }
}
- return;
}
/*
@@ -98834,13 +102161,14 @@ SQLITE_PRIVATE void sqlite3ResetOneSchema(sqlite3 *db, int iDb){
SQLITE_PRIVATE void sqlite3ResetAllSchemasOfConnection(sqlite3 *db){
int i;
sqlite3BtreeEnterAll(db);
+ assert( db->nSchemaLock==0 );
for(i=0; inDb; i++){
Db *pDb = &db->aDb[i];
if( pDb->pSchema ){
sqlite3SchemaClear(pDb->pSchema);
}
}
- db->flags &= ~SQLITE_InternChanges;
+ db->mDbFlags &= ~DBFLAG_SchemaChange;
sqlite3VtabUnlockList(db);
sqlite3BtreeLeaveAll(db);
sqlite3CollapseDatabaseArray(db);
@@ -98850,7 +102178,7 @@ SQLITE_PRIVATE void sqlite3ResetAllSchemasOfConnection(sqlite3 *db){
** This routine is called when a commit occurs.
*/
SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3 *db){
- db->flags &= ~SQLITE_InternChanges;
+ db->mDbFlags &= ~DBFLAG_SchemaChange;
}
/*
@@ -98888,13 +102216,16 @@ SQLITE_PRIVATE void sqlite3DeleteColumnNames(sqlite3 *db, Table *pTable){
*/
static void SQLITE_NOINLINE deleteTable(sqlite3 *db, Table *pTable){
Index *pIndex, *pNext;
- TESTONLY( int nLookaside; ) /* Used to verify lookaside not used for schema */
+#ifdef SQLITE_DEBUG
/* Record the number of outstanding lookaside allocations in schema Tables
** prior to doing any free() operations. Since schema Tables do not use
** lookaside, this number should not change. */
- TESTONLY( nLookaside = (db && (pTable->tabFlags & TF_Ephemeral)==0) ?
- db->lookaside.nOut : 0 );
+ int nLookaside = 0;
+ if( db && (pTable->tabFlags & TF_Ephemeral)==0 ){
+ nLookaside = sqlite3LookasideUsed(db, 0);
+ }
+#endif
/* Delete all indices associated with this table. */
for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){
@@ -98928,12 +102259,12 @@ static void SQLITE_NOINLINE deleteTable(sqlite3 *db, Table *pTable){
sqlite3DbFree(db, pTable);
/* Verify that no lookaside memory was used by schema tables */
- assert( nLookaside==0 || nLookaside==db->lookaside.nOut );
+ assert( nLookaside==0 || nLookaside==sqlite3LookasideUsed(db,0) );
}
SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3 *db, Table *pTable){
/* Do not delete the table until the reference count reaches zero. */
if( !pTable ) return;
- if( ((!db || db->pnBytesFreed==0) && (--pTable->nRef)>0) ) return;
+ if( ((!db || db->pnBytesFreed==0) && (--pTable->nTabRef)>0) ) return;
deleteTable(db, pTable);
}
@@ -98954,7 +102285,7 @@ SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char
pDb = &db->aDb[iDb];
p = sqlite3HashInsert(&pDb->pSchema->tblHash, zTabName, 0);
sqlite3DeleteTable(db, p);
- db->flags |= SQLITE_InternChanges;
+ db->mDbFlags |= DBFLAG_SchemaChange;
}
/*
@@ -98987,7 +102318,7 @@ SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3 *db, Token *pName){
*/
SQLITE_PRIVATE void sqlite3OpenMasterTable(Parse *p, int iDb){
Vdbe *v = sqlite3GetVdbe(p);
- sqlite3TableLock(p, iDb, MASTER_ROOT, 1, SCHEMA_TABLE(iDb));
+ sqlite3TableLock(p, iDb, MASTER_ROOT, 1, MASTER_NAME);
sqlite3VdbeAddOp4Int(v, OP_OpenWrite, 0, MASTER_ROOT, iDb, 5);
if( p->nTab==0 ){
p->nTab = 1;
@@ -99005,7 +102336,10 @@ SQLITE_PRIVATE int sqlite3FindDbName(sqlite3 *db, const char *zName){
if( zName ){
Db *pDb;
for(i=(db->nDb-1), pDb=&db->aDb[i]; i>=0; i--, pDb--){
- if( 0==sqlite3StrICmp(pDb->zDbSName, zName) ) break;
+ if( 0==sqlite3_stricmp(pDb->zDbSName, zName) ) break;
+ /* "main" is always an acceptable alias for the primary database
+ ** even if it has been renamed using SQLITE_DBCONFIG_MAINDBNAME. */
+ if( i==0 && 0==sqlite3_stricmp("main", zName) ) break;
}
}
return i;
@@ -99064,7 +102398,8 @@ SQLITE_PRIVATE int sqlite3TwoPartName(
return -1;
}
}else{
- assert( db->init.iDb==0 || db->init.busy || (db->flags & SQLITE_Vacuum)!=0);
+ assert( db->init.iDb==0 || db->init.busy
+ || (db->mDbFlags & DBFLAG_Vacuum)!=0);
iDb = db->init.iDb;
*pUnqual = pName1;
}
@@ -99224,8 +102559,12 @@ SQLITE_PRIVATE void sqlite3StartTable(
pTable->zName = zName;
pTable->iPKey = -1;
pTable->pSchema = db->aDb[iDb].pSchema;
- pTable->nRef = 1;
+ pTable->nTabRef = 1;
+#ifdef SQLITE_DEFAULT_ROWEST
+ pTable->nRowLogEst = sqlite3LogEst(SQLITE_DEFAULT_ROWEST);
+#else
pTable->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
+#endif
assert( pParse->pNewTable==0 );
pParse->pNewTable = pTable;
@@ -99292,7 +102631,8 @@ SQLITE_PRIVATE void sqlite3StartTable(
}else
#endif
{
- pParse->addrCrTab = sqlite3VdbeAddOp2(v, OP_CreateTable, iDb, reg2);
+ pParse->addrCrTab =
+ sqlite3VdbeAddOp3(v, OP_CreateBtree, iDb, reg2, BTREE_INTKEY);
}
sqlite3OpenMasterTable(pParse, iDb);
sqlite3VdbeAddOp2(v, OP_NewRowid, 0, reg1);
@@ -99341,12 +102681,10 @@ SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){
Column *pCol;
sqlite3 *db = pParse->db;
if( (p = pParse->pNewTable)==0 ) return;
-#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 = sqlite3DbMallocRaw(db, pName->n + pType->n + 2);
if( z==0 ) return;
memcpy(z, pName->z, pName->n);
@@ -99401,6 +102739,7 @@ SQLITE_PRIVATE void sqlite3AddNotNull(Parse *pParse, int onError){
p = pParse->pNewTable;
if( p==0 || NEVER(p->nCol<1) ) return;
p->aCol[p->nCol-1].notNull = (u8)onError;
+ p->tabFlags |= TF_HasNotNull;
}
/*
@@ -99500,34 +102839,37 @@ SQLITE_PRIVATE char sqlite3AffinityType(const char *zIn, u8 *pszEst){
** This routine is called by the parser while in the middle of
** parsing a CREATE TABLE statement.
*/
-SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse *pParse, ExprSpan *pSpan){
+SQLITE_PRIVATE void sqlite3AddDefaultValue(
+ Parse *pParse, /* Parsing context */
+ Expr *pExpr, /* The parsed expression of the default value */
+ const char *zStart, /* Start of the default value text */
+ const char *zEnd /* First character past end of defaut value text */
+){
Table *p;
Column *pCol;
sqlite3 *db = pParse->db;
p = pParse->pNewTable;
if( p!=0 ){
pCol = &(p->aCol[p->nCol-1]);
- if( !sqlite3ExprIsConstantOrFunction(pSpan->pExpr, db->init.busy) ){
+ if( !sqlite3ExprIsConstantOrFunction(pExpr, db->init.busy) ){
sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant",
pCol->zName);
}else{
/* A copy of pExpr is used instead of the original, as pExpr contains
- ** tokens that point to volatile memory. The 'span' of the expression
- ** is required by pragma table_info.
+ ** tokens that point to volatile memory.
*/
Expr x;
sqlite3ExprDelete(db, pCol->pDflt);
memset(&x, 0, sizeof(x));
x.op = TK_SPAN;
- x.u.zToken = sqlite3DbStrNDup(db, (char*)pSpan->zStart,
- (int)(pSpan->zEnd - pSpan->zStart));
- x.pLeft = pSpan->pExpr;
+ x.u.zToken = sqlite3DbSpanDup(db, zStart, zEnd);
+ x.pLeft = pExpr;
x.flags = EP_Skip;
pCol->pDflt = sqlite3ExprDup(db, &x, EXPRDUP_REDUCE);
sqlite3DbFree(db, x.u.zToken);
}
}
- sqlite3ExprDelete(db, pSpan->pExpr);
+ sqlite3ExprDelete(db, pExpr);
}
/*
@@ -99951,9 +103293,8 @@ static int hasColumn(const i16 *aiCol, int nCol, int x){
** Changes include:
**
** (1) Set all columns of the PRIMARY KEY schema object to be NOT NULL.
-** (2) Convert the OP_CreateTable into an OP_CreateIndex. There is
-** no rowid btree for a WITHOUT ROWID. Instead, the canonical
-** data storage is a covering index btree.
+** (2) Convert P3 parameter of the OP_CreateBtree from BTREE_INTKEY
+** into BTREE_BLOBKEY.
** (3) Bypass the creation of the sqlite_master table entry
** for the PRIMARY KEY as the primary key index is now
** identified by the sqlite_master table entry of the table itself.
@@ -99961,7 +103302,7 @@ static int hasColumn(const i16 *aiCol, int nCol, int x){
** schema to the rootpage from the main table.
** (5) Add all table columns to the PRIMARY KEY Index object
** so that the PRIMARY KEY is a covering index. The surplus
-** columns are part of KeyInfo.nXField and are not used for
+** columns are part of KeyInfo.nAllField and are not used for
** sorting or lookup or uniqueness checks.
** (6) Replace the rowid tail on all automatically generated UNIQUE
** indices with the PRIMARY KEY columns.
@@ -99990,13 +103331,12 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
** virtual tables */
if( IN_DECLARE_VTAB ) return;
- /* Convert the OP_CreateTable opcode that would normally create the
- ** root-page for the table into an OP_CreateIndex opcode. The index
- ** created will become the PRIMARY KEY index.
+ /* Convert the P3 operand of the OP_CreateBtree opcode from BTREE_INTKEY
+ ** into BTREE_BLOBKEY.
*/
if( pParse->addrCrTab ){
assert( v );
- sqlite3VdbeChangeOpcode(v, pParse->addrCrTab, OP_CreateIndex);
+ sqlite3VdbeChangeP3(v, pParse->addrCrTab, BTREE_BLOBKEY);
}
/* Locate the PRIMARY KEY index. Or, if this table was originally
@@ -100019,15 +103359,6 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
}else{
pPk = sqlite3PrimaryKeyIndex(pTab);
- /* Bypass the creation of the PRIMARY KEY btree and the sqlite_master
- ** table entry. This is only required if currently generating VDBE
- ** code for a CREATE TABLE (not when parsing one as part of reading
- ** a database schema). */
- if( v ){
- assert( db->init.busy==0 );
- sqlite3VdbeChangeOpcode(v, pPk->tnum, OP_Goto);
- }
-
/*
** Remove all redundant columns from the PRIMARY KEY. For example, change
** "PRIMARY KEY(a,b,a,b,c,b,c,d)" into just "PRIMARY KEY(a,b,c,d)". Later
@@ -100047,6 +103378,15 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
if( !db->init.imposterTable ) pPk->uniqNotNull = 1;
nPk = pPk->nKeyCol;
+ /* Bypass the creation of the PRIMARY KEY btree and the sqlite_master
+ ** table entry. This is only required if currently generating VDBE
+ ** code for a CREATE TABLE (not when parsing one as part of reading
+ ** a database schema). */
+ if( v && pPk->tnum>0 ){
+ assert( db->init.busy==0 );
+ sqlite3VdbeChangeOpcode(v, pPk->tnum, OP_Goto);
+ }
+
/* The root page of the PRIMARY KEY is the table root page */
pPk->tnum = pTab->tnum;
@@ -100246,10 +103586,6 @@ SQLITE_PRIVATE void sqlite3EndTable(
pParse->nTab = 2;
addrTop = sqlite3VdbeCurrentAddr(v) + 1;
sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop);
- sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield);
- sqlite3Select(pParse, pSelect, &dest);
- sqlite3VdbeEndCoroutine(v, regYield);
- sqlite3VdbeJumpHere(v, addrTop - 1);
if( pParse->nErr ) return;
pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect);
if( pSelTab==0 ) return;
@@ -100259,6 +103595,11 @@ SQLITE_PRIVATE void sqlite3EndTable(
pSelTab->nCol = 0;
pSelTab->aCol = 0;
sqlite3DeleteTable(db, pSelTab);
+ sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield);
+ sqlite3Select(pParse, pSelect, &dest);
+ if( pParse->nErr ) return;
+ sqlite3VdbeEndCoroutine(v, regYield);
+ sqlite3VdbeJumpHere(v, addrTop - 1);
addrInsLoop = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm);
VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_MakeRecord, dest.iSdst, dest.nSdst, regRec);
@@ -100290,7 +103631,7 @@ SQLITE_PRIVATE void sqlite3EndTable(
"UPDATE %Q.%s "
"SET type='%s', name=%Q, tbl_name=%Q, rootpage=#%d, sql=%Q "
"WHERE rowid=#%d",
- db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb),
+ db->aDb[iDb].zDbSName, MASTER_NAME,
zType,
p->zName,
p->zName,
@@ -100336,7 +103677,7 @@ SQLITE_PRIVATE void sqlite3EndTable(
return;
}
pParse->pNewTable = 0;
- db->flags |= SQLITE_InternChanges;
+ db->mDbFlags |= DBFLAG_SchemaChange;
#ifndef SQLITE_OMIT_ALTERTABLE
if( !p->pSelect ){
@@ -100401,7 +103742,7 @@ SQLITE_PRIVATE void sqlite3CreateView(
** the end.
*/
sEnd = pParse->sLastToken;
- assert( sEnd.z[0]!=0 );
+ assert( sEnd.z[0]!=0 || sEnd.n==0 );
if( sEnd.z[0]!=';' ){
sEnd.z += sEnd.n;
}
@@ -100435,6 +103776,9 @@ SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
int nErr = 0; /* Number of errors encountered */
int n; /* Temporarily holds the number of cursors assigned */
sqlite3 *db = pParse->db; /* Database connection for malloc errors */
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ int rc;
+#endif
#ifndef SQLITE_OMIT_AUTHORIZATION
sqlite3_xauth xAuth; /* Saved xAuth pointer */
#endif
@@ -100442,8 +103786,11 @@ SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
assert( pTable );
#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( sqlite3VtabCallConnect(pParse, pTable) ){
- return SQLITE_ERROR;
+ db->nSchemaLock++;
+ rc = sqlite3VtabCallConnect(pParse, pTable);
+ db->nSchemaLock--;
+ if( rc ){
+ return 1;
}
if( IsVirtual(pTable) ) return 0;
#endif
@@ -100627,7 +103974,7 @@ static void destroyRootPage(Parse *pParse, int iTable, int iDb){
*/
sqlite3NestedParse(pParse,
"UPDATE %Q.%s SET rootpage=%d WHERE #%d AND rootpage=#%d",
- pParse->db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb), iTable, r1, r1);
+ pParse->db->aDb[iDb].zDbSName, MASTER_NAME, iTable, r1, r1);
#endif
sqlite3ReleaseTempReg(pParse, r1);
}
@@ -100639,14 +103986,6 @@ static void destroyRootPage(Parse *pParse, int iTable, int iDb){
** is also added (this can happen with an auto-vacuum database).
*/
static void destroyTable(Parse *pParse, Table *pTab){
-#ifdef SQLITE_OMIT_AUTOVACUUM
- Index *pIdx;
- int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
- destroyRootPage(pParse, pTab->tnum, iDb);
- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- destroyRootPage(pParse, pIdx->tnum, iDb);
- }
-#else
/* If the database may be auto-vacuum capable (if SQLITE_OMIT_AUTOVACUUM
** is not defined), then it is important to call OP_Destroy on the
** table and index root-pages in order, starting with the numerically
@@ -100689,7 +104028,6 @@ static void destroyTable(Parse *pParse, Table *pTab){
iDestroyed = iLargest;
}
}
-#endif
}
/*
@@ -100770,7 +104108,7 @@ SQLITE_PRIVATE void sqlite3CodeDropTable(Parse *pParse, Table *pTab, int iDb, in
*/
sqlite3NestedParse(pParse,
"DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'",
- pDb->zDbSName, SCHEMA_TABLE(iDb), pTab->zName);
+ pDb->zDbSName, MASTER_NAME, pTab->zName);
if( !isView && !IsVirtual(pTab) ){
destroyTable(pParse, pTab);
}
@@ -101116,8 +104454,8 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
addr2 = sqlite3VdbeCurrentAddr(v);
}
sqlite3VdbeAddOp3(v, OP_SorterData, iSorter, regRecord, iIdx);
- sqlite3VdbeAddOp3(v, OP_Last, iIdx, 0, -1);
- sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 0);
+ sqlite3VdbeAddOp1(v, OP_SeekEnd, iIdx);
+ sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdx, regRecord);
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
sqlite3ReleaseTempReg(pParse, regRecord);
sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2); VdbeCoverage(v);
@@ -101605,7 +104943,7 @@ SQLITE_PRIVATE void sqlite3CreateIndex(
sqlite3OomFault(db);
goto exit_create_index;
}
- db->flags |= SQLITE_InternChanges;
+ db->mDbFlags |= DBFLAG_SchemaChange;
if( pTblName!=0 ){
pIndex->tnum = db->init.newTnum;
}
@@ -101641,7 +104979,7 @@ SQLITE_PRIVATE void sqlite3CreateIndex(
** that case the convertToWithoutRowidTable() routine will replace
** the Noop with a Goto to jump over the VDBE code generated below. */
pIndex->tnum = sqlite3VdbeAddOp0(v, OP_Noop);
- sqlite3VdbeAddOp2(v, OP_CreateIndex, iDb, iMem);
+ sqlite3VdbeAddOp3(v, OP_CreateBtree, iDb, iMem, BTREE_BLOBKEY);
/* Gather the complete text of the CREATE INDEX statement into
** the zStmt variable
@@ -101662,7 +105000,7 @@ SQLITE_PRIVATE void sqlite3CreateIndex(
*/
sqlite3NestedParse(pParse,
"INSERT INTO %Q.%s VALUES('index',%Q,%Q,#%d,%Q);",
- db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb),
+ db->aDb[iDb].zDbSName, MASTER_NAME,
pIndex->zName,
pTab->zName,
iMem,
@@ -101740,6 +105078,9 @@ SQLITE_PRIVATE void sqlite3DefaultRowEst(Index *pIdx){
int nCopy = MIN(ArraySize(aVal), pIdx->nKeyCol);
int i;
+ /* Indexes with default row estimates should not have stat1 data */
+ assert( !pIdx->hasStat1 );
+
/* Set the first entry (number of rows in the index) to the estimated
** number of rows in the table, or half the number of rows in the table
** for a partial index. But do not let the estimate drop below 10. */
@@ -101814,7 +105155,7 @@ SQLITE_PRIVATE void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists
sqlite3BeginWriteOperation(pParse, 1, iDb);
sqlite3NestedParse(pParse,
"DELETE FROM %Q.%s WHERE name=%Q AND type='index'",
- db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb), pIndex->zName
+ db->aDb[iDb].zDbSName, MASTER_NAME, pIndex->zName
);
sqlite3ClearStatTables(pParse, iDb, "idx", pIndex->zName);
sqlite3ChangeCookie(pParse, iDb);
@@ -101905,7 +105246,7 @@ SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3 *db, IdList *pList){
sqlite3DbFree(db, pList->a[i].zName);
}
sqlite3DbFree(db, pList->a);
- sqlite3DbFree(db, pList);
+ sqlite3DbFreeNN(db, pList);
}
/*
@@ -101957,7 +105298,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(
/* Allocate additional space if needed */
if( (u32)pSrc->nSrc+nExtra>pSrc->nAlloc ){
SrcList *pNew;
- int nAlloc = pSrc->nSrc+nExtra;
+ int nAlloc = pSrc->nSrc*2+nExtra;
int nGot;
pNew = sqlite3DbRealloc(db, pSrc,
sizeof(*pSrc) + (nAlloc-1)*sizeof(pSrc->a[0]) );
@@ -102035,9 +105376,12 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(
pList = sqlite3DbMallocRawNN(db, sizeof(SrcList) );
if( pList==0 ) return 0;
pList->nAlloc = 1;
- pList->nSrc = 0;
+ pList->nSrc = 1;
+ memset(&pList->a[0], 0, sizeof(pList->a[0]));
+ pList->a[0].iCursor = -1;
+ }else{
+ pList = sqlite3SrcListEnlarge(db, pList, 1, pList->nSrc);
}
- pList = sqlite3SrcListEnlarge(db, pList, 1, pList->nSrc);
if( db->mallocFailed ){
sqlite3SrcListDelete(db, pList);
return 0;
@@ -102047,12 +105391,12 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(
pDatabase = 0;
}
if( pDatabase ){
- Token *pTemp = pDatabase;
- pDatabase = pTable;
- pTable = pTemp;
+ pItem->zName = sqlite3NameFromToken(db, pDatabase);
+ pItem->zDatabase = sqlite3NameFromToken(db, pTable);
+ }else{
+ pItem->zName = sqlite3NameFromToken(db, pTable);
+ pItem->zDatabase = 0;
}
- pItem->zName = sqlite3NameFromToken(db, pTable);
- pItem->zDatabase = sqlite3NameFromToken(db, pDatabase);
return pList;
}
@@ -102092,7 +105436,7 @@ SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){
sqlite3ExprDelete(db, pItem->pOn);
sqlite3IdListDelete(db, pItem->pUsing);
}
- sqlite3DbFree(db, pList);
+ sqlite3DbFreeNN(db, pList);
}
/*
@@ -102130,9 +105474,10 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm(
goto append_from_error;
}
p = sqlite3SrcListAppend(db, p, pTable, pDatabase);
- if( p==0 || NEVER(p->nSrc==0) ){
+ if( p==0 ){
goto append_from_error;
}
+ assert( p->nSrc>0 );
pItem = &p->a[p->nSrc-1];
assert( pAlias!=0 );
if( pAlias->n ){
@@ -102157,8 +105502,10 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm(
*/
SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pIndexedBy){
assert( pIndexedBy!=0 );
- if( p && ALWAYS(p->nSrc>0) ){
- struct SrcList_item *pItem = &p->a[p->nSrc-1];
+ if( p && pIndexedBy->n>0 ){
+ struct SrcList_item *pItem;
+ assert( p->nSrc>0 );
+ pItem = &p->a[p->nSrc-1];
assert( pItem->fg.notIndexed==0 );
assert( pItem->fg.isIndexedBy==0 );
assert( pItem->fg.isTabFunc==0 );
@@ -102168,7 +105515,7 @@ SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pI
pItem->fg.notIndexed = 1;
}else{
pItem->u1.zIndexedBy = sqlite3NameFromToken(pParse->db, pIndexedBy);
- pItem->fg.isIndexedBy = (pItem->u1.zIndexedBy!=0);
+ pItem->fg.isIndexedBy = 1;
}
}
}
@@ -102241,36 +105588,25 @@ SQLITE_PRIVATE void sqlite3BeginTransaction(Parse *pParse, int type){
}
/*
-** Generate VDBE code for a COMMIT statement.
-*/
-SQLITE_PRIVATE void sqlite3CommitTransaction(Parse *pParse){
- Vdbe *v;
-
- assert( pParse!=0 );
- assert( pParse->db!=0 );
- if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "COMMIT", 0, 0) ){
- return;
- }
- v = sqlite3GetVdbe(pParse);
- if( v ){
- sqlite3VdbeAddOp1(v, OP_AutoCommit, 1);
- }
-}
-
-/*
-** Generate VDBE code for a ROLLBACK statement.
+** Generate VDBE code for a COMMIT or ROLLBACK statement.
+** Code for ROLLBACK is generated if eType==TK_ROLLBACK. Otherwise
+** code is generated for a COMMIT.
*/
-SQLITE_PRIVATE void sqlite3RollbackTransaction(Parse *pParse){
+SQLITE_PRIVATE void sqlite3EndTransaction(Parse *pParse, int eType){
Vdbe *v;
+ int isRollback;
assert( pParse!=0 );
assert( pParse->db!=0 );
- if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "ROLLBACK", 0, 0) ){
+ assert( eType==TK_COMMIT || eType==TK_END || eType==TK_ROLLBACK );
+ isRollback = eType==TK_ROLLBACK;
+ if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION,
+ isRollback ? "ROLLBACK" : "COMMIT", 0, 0) ){
return;
}
v = sqlite3GetVdbe(pParse);
if( v ){
- sqlite3VdbeAddOp2(v, OP_AutoCommit, 1, 1);
+ sqlite3VdbeAddOp2(v, OP_AutoCommit, 1, isRollback);
}
}
@@ -102460,7 +105796,9 @@ SQLITE_PRIVATE void sqlite3UniqueConstraint(
assert( pIdx->aiColumn[j]>=0 );
zCol = pTab->aCol[pIdx->aiColumn[j]].zName;
if( j ) sqlite3StrAccumAppend(&errMsg, ", ", 2);
- sqlite3XPrintf(&errMsg, "%s.%s", pTab->zName, zCol);
+ sqlite3StrAccumAppendAll(&errMsg, pTab->zName);
+ sqlite3StrAccumAppend(&errMsg, ".", 1);
+ sqlite3StrAccumAppendAll(&errMsg, zCol);
}
}
zErr = sqlite3StrAccumFinish(&errMsg);
@@ -102648,6 +105986,18 @@ SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){
pKey->aSortOrder[i] = pIdx->aSortOrder[i];
}
if( pParse->nErr ){
+ assert( pParse->rc==SQLITE_ERROR_MISSING_COLLSEQ );
+ if( pIdx->bNoQuery==0 ){
+ /* Deactivate the index because it contains an unknown collating
+ ** sequence. The only way to reactive the index is to reload the
+ ** schema. Adding the missing collating sequence later does not
+ ** reactive the index. The application had the chance to register
+ ** the missing index using the collation-needed callback. For
+ ** simplicity, SQLite will not give the application a second chance.
+ */
+ pIdx->bNoQuery = 1;
+ pParse->rc = SQLITE_ERROR_RETRY;
+ }
sqlite3KeyInfoUnref(pKey);
pKey = 0;
}
@@ -102833,6 +106183,7 @@ SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(
assert( !p || p->xCmp );
if( p==0 ){
sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName);
+ pParse->rc = SQLITE_ERROR_MISSING_COLLSEQ;
}
return p;
}
@@ -102849,7 +106200,7 @@ SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(
** from the main database is substituted, if one is available.
*/
SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *pParse, CollSeq *pColl){
- if( pColl ){
+ if( pColl && pColl->xCmp==0 ){
const char *zName = pColl->zName;
sqlite3 *db = pParse->db;
CollSeq *p = sqlite3GetCollSeq(pParse, ENC(db), pColl, zName);
@@ -102885,8 +106236,8 @@ static CollSeq *findCollSeqEntry(
pColl = sqlite3HashFind(&db->aCollSeq, zName);
if( 0==pColl && create ){
- int nName = sqlite3Strlen30(zName);
- pColl = sqlite3DbMallocZero(db, 3*sizeof(*pColl) + nName + 1);
+ int nName = sqlite3Strlen30(zName) + 1;
+ pColl = sqlite3DbMallocZero(db, 3*sizeof(*pColl) + nName);
if( pColl ){
CollSeq *pDel = 0;
pColl[0].zName = (char*)&pColl[3];
@@ -102896,7 +106247,6 @@ static CollSeq *findCollSeqEntry(
pColl[2].zName = (char*)&pColl[3];
pColl[2].enc = SQLITE_UTF16BE;
memcpy(pColl[0].zName, zName, nName);
- pColl[0].zName[nName] = 0;
pDel = sqlite3HashInsert(&db->aCollSeq, pColl[0].zName, pColl);
/* If a malloc() failure occurred in sqlite3HashInsert(), it will
@@ -103036,7 +106386,8 @@ SQLITE_PRIVATE void sqlite3InsertBuiltinFuncs(
FuncDef *pOther;
const char *zName = aDef[i].zName;
int nName = sqlite3Strlen30(zName);
- int h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % SQLITE_FUNC_HASH_SZ;
+ int h = (zName[0] + nName) % SQLITE_FUNC_HASH_SZ;
+ assert( zName[0]>='a' && zName[0]<='z' );
pOther = functionSearch(h, zName);
if( pOther ){
assert( pOther!=&aDef[i] && pOther->pNext!=&aDef[i] );
@@ -103102,7 +106453,7 @@ SQLITE_PRIVATE FuncDef *sqlite3FindFunction(
/* If no match is found, search the built-in functions.
**
- ** If the SQLITE_PreferBuiltin flag is set, then search the built-in
+ ** If the DBFLAG_PreferBuiltin flag is set, then search the built-in
** functions even if a prior app-defined function was found. And give
** priority to built-in functions.
**
@@ -103112,7 +106463,7 @@ SQLITE_PRIVATE FuncDef *sqlite3FindFunction(
** new function. But the FuncDefs for built-in functions are read-only.
** So we must not search for built-ins when creating a new function.
*/
- if( !createFlag && (pBest==0 || (db->flags & SQLITE_PreferBuiltin)!=0) ){
+ if( !createFlag && (pBest==0 || (db->mDbFlags & DBFLAG_PreferBuiltin)!=0) ){
bestScore = 0;
h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % SQLITE_FUNC_HASH_SZ;
p = functionSearch(h, zName);
@@ -103185,8 +106536,8 @@ SQLITE_PRIVATE void sqlite3SchemaClear(void *p){
pSchema->pSeqTab = 0;
if( pSchema->schemaFlags & DB_SchemaLoaded ){
pSchema->iGeneration++;
- pSchema->schemaFlags &= ~DB_SchemaLoaded;
}
+ pSchema->schemaFlags &= ~(DB_SchemaLoaded|DB_ResetWanted);
}
/*
@@ -103252,7 +106603,7 @@ SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
sqlite3DeleteTable(pParse->db, pItem->pTab);
pItem->pTab = pTab;
if( pTab ){
- pTab->nRef++;
+ pTab->nTabRef++;
}
if( sqlite3IndexedByLookup(pParse, pItem) ){
pTab = 0;
@@ -103306,6 +106657,8 @@ SQLITE_PRIVATE void sqlite3MaterializeView(
Parse *pParse, /* Parsing context */
Table *pView, /* View definition */
Expr *pWhere, /* Optional WHERE clause to be added */
+ ExprList *pOrderBy, /* Optional ORDER BY clause */
+ Expr *pLimit, /* Optional LIMIT clause */
int iCur /* Cursor number for ephemeral table */
){
SelectDest dest;
@@ -103322,8 +106675,8 @@ SQLITE_PRIVATE void sqlite3MaterializeView(
assert( pFrom->a[0].pOn==0 );
assert( pFrom->a[0].pUsing==0 );
}
- pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0,
- SF_IncludeHidden, 0, 0);
+ pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, pOrderBy,
+ SF_IncludeHidden, pLimit);
sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
sqlite3Select(pParse, pSel, &dest);
sqlite3SelectDelete(db, pSel);
@@ -103345,29 +106698,29 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere(
Expr *pWhere, /* The WHERE clause. May be null */
ExprList *pOrderBy, /* The ORDER BY clause. May be null */
Expr *pLimit, /* The LIMIT clause. May be null */
- Expr *pOffset, /* The OFFSET clause. May be null */
char *zStmtType /* Either DELETE or UPDATE. For err msgs. */
){
- Expr *pWhereRowid = NULL; /* WHERE rowid .. */
+ sqlite3 *db = pParse->db;
+ Expr *pLhs = NULL; /* LHS of IN(SELECT...) operator */
Expr *pInClause = NULL; /* WHERE rowid IN ( select ) */
- Expr *pSelectRowid = NULL; /* SELECT rowid ... */
ExprList *pEList = NULL; /* Expression list contaning only pSelectRowid */
SrcList *pSelectSrc = NULL; /* SELECT rowid FROM x ... (dup of pSrc) */
Select *pSelect = NULL; /* Complete SELECT tree */
+ Table *pTab;
/* Check that there isn't an ORDER BY without a LIMIT clause.
*/
- if( pOrderBy && (pLimit == 0) ) {
+ if( pOrderBy && pLimit==0 ) {
sqlite3ErrorMsg(pParse, "ORDER BY without LIMIT on %s", zStmtType);
- goto limit_where_cleanup;
+ sqlite3ExprDelete(pParse->db, pWhere);
+ sqlite3ExprListDelete(pParse->db, pOrderBy);
+ return 0;
}
/* We only need to generate a select expression if there
** is a limit/offset term to enforce.
*/
if( pLimit == 0 ) {
- /* if pLimit is null, pOffset will always be null as well. */
- assert( pOffset == 0 );
return pWhere;
}
@@ -103380,36 +106733,47 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere(
** );
*/
- pSelectRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0, 0);
- if( pSelectRowid == 0 ) goto limit_where_cleanup;
- pEList = sqlite3ExprListAppend(pParse, 0, pSelectRowid);
- if( pEList == 0 ) goto limit_where_cleanup;
+ pTab = pSrc->a[0].pTab;
+ if( HasRowid(pTab) ){
+ pLhs = sqlite3PExpr(pParse, TK_ROW, 0, 0);
+ pEList = sqlite3ExprListAppend(
+ pParse, 0, sqlite3PExpr(pParse, TK_ROW, 0, 0)
+ );
+ }else{
+ Index *pPk = sqlite3PrimaryKeyIndex(pTab);
+ if( pPk->nKeyCol==1 ){
+ const char *zName = pTab->aCol[pPk->aiColumn[0]].zName;
+ pLhs = sqlite3Expr(db, TK_ID, zName);
+ pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ID, zName));
+ }else{
+ int i;
+ for(i=0; inKeyCol; i++){
+ Expr *p = sqlite3Expr(db, TK_ID, pTab->aCol[pPk->aiColumn[i]].zName);
+ pEList = sqlite3ExprListAppend(pParse, pEList, p);
+ }
+ pLhs = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
+ if( pLhs ){
+ pLhs->x.pList = sqlite3ExprListDup(db, pEList, 0);
+ }
+ }
+ }
/* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree
** and the SELECT subtree. */
+ pSrc->a[0].pTab = 0;
pSelectSrc = sqlite3SrcListDup(pParse->db, pSrc, 0);
- if( pSelectSrc == 0 ) {
- sqlite3ExprListDelete(pParse->db, pEList);
- goto limit_where_cleanup;
- }
+ pSrc->a[0].pTab = pTab;
+ pSrc->a[0].pIBIndex = 0;
/* generate the SELECT expression tree. */
- pSelect = sqlite3SelectNew(pParse,pEList,pSelectSrc,pWhere,0,0,
- pOrderBy,0,pLimit,pOffset);
- if( pSelect == 0 ) return 0;
+ pSelect = sqlite3SelectNew(pParse, pEList, pSelectSrc, pWhere, 0 ,0,
+ pOrderBy,0,pLimit
+ );
/* now generate the new WHERE rowid IN clause for the DELETE/UDPATE */
- pWhereRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0, 0);
- pInClause = pWhereRowid ? sqlite3PExpr(pParse, TK_IN, pWhereRowid, 0, 0) : 0;
+ pInClause = sqlite3PExpr(pParse, TK_IN, pLhs, 0);
sqlite3PExprAddSelect(pParse, pInClause, pSelect);
return pInClause;
-
-limit_where_cleanup:
- sqlite3ExprDelete(pParse->db, pWhere);
- sqlite3ExprListDelete(pParse->db, pOrderBy);
- sqlite3ExprDelete(pParse->db, pLimit);
- sqlite3ExprDelete(pParse->db, pOffset);
- return 0;
}
#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) */
/* && !defined(SQLITE_OMIT_SUBQUERY) */
@@ -103424,7 +106788,9 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere(
SQLITE_PRIVATE void sqlite3DeleteFrom(
Parse *pParse, /* The parser context */
SrcList *pTabList, /* The table from which we should delete things */
- Expr *pWhere /* The WHERE clause. May be null */
+ Expr *pWhere, /* The WHERE clause. May be null */
+ ExprList *pOrderBy, /* ORDER BY clause. May be null */
+ Expr *pLimit /* LIMIT clause. May be null */
){
Vdbe *v; /* The virtual database engine */
Table *pTab; /* The table from which records will be deleted */
@@ -103469,6 +106835,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
}
assert( pTabList->nSrc==1 );
+
/* Locate the table which we want to delete. This table has to be
** put in an SrcList structure because some of the subroutines we
** will be calling are designed to work with multiple tables and expect
@@ -103483,16 +106850,26 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
#ifndef SQLITE_OMIT_TRIGGER
pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
isView = pTab->pSelect!=0;
- bComplex = pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0);
#else
# define pTrigger 0
# define isView 0
#endif
+ bComplex = pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0);
#ifdef SQLITE_OMIT_VIEW
# undef isView
# define isView 0
#endif
+#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
+ if( !isView ){
+ pWhere = sqlite3LimitWhere(
+ pParse, pTabList, pWhere, pOrderBy, pLimit, "DELETE"
+ );
+ pOrderBy = 0;
+ pLimit = 0;
+ }
+#endif
+
/* If pTab is really a view, make sure it has been initialized.
*/
if( sqlite3ViewGetColumnNames(pParse, pTab) ){
@@ -103540,8 +106917,12 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
*/
#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
if( isView ){
- sqlite3MaterializeView(pParse, pTab, pWhere, iTabCur);
+ sqlite3MaterializeView(pParse, pTab,
+ pWhere, pOrderBy, pLimit, iTabCur
+ );
iDataCur = iIdxCur = iTabCur;
+ pOrderBy = 0;
+ pLimit = 0;
}
#endif
@@ -103566,7 +106947,14 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
/* Special case: A DELETE without a WHERE clause deletes everything.
** It is easier just to erase the whole table. Prior to version 3.6.5,
** this optimization caused the row change count (the value returned by
- ** API function sqlite3_count_changes) to be set incorrectly. */
+ ** API function sqlite3_count_changes) to be set incorrectly.
+ **
+ ** The "rcauth==SQLITE_OK" terms is the
+ ** IMPLEMENTATION-OF: R-17228-37124 If the action code is SQLITE_DELETE and
+ ** the callback returns SQLITE_IGNORE then the DELETE operation proceeds but
+ ** the truncate optimization is disabled and all rows are deleted
+ ** individually.
+ */
if( rcauth==SQLITE_OK
&& pWhere==0
&& !bComplex
@@ -103665,10 +107053,10 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
nKey = 0; /* Zero tells OP_Found to use a composite key */
sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, iKey,
sqlite3IndexAffinityStr(pParse->db, pPk), nPk);
- sqlite3VdbeAddOp2(v, OP_IdxInsert, iEphCur, iKey);
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iEphCur, iKey, iPk, nPk);
}else{
/* Add the rowid of the row to be deleted to the RowSet */
- nKey = 1; /* OP_Seek always uses a single rowid */
+ nKey = 1; /* OP_DeferredSeek always uses a single rowid */
sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, iKey);
}
}
@@ -103711,7 +107099,11 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
}
}else if( pPk ){
addrLoop = sqlite3VdbeAddOp1(v, OP_Rewind, iEphCur); VdbeCoverage(v);
- sqlite3VdbeAddOp2(v, OP_RowKey, iEphCur, iKey);
+ if( IsVirtual(pTab) ){
+ sqlite3VdbeAddOp3(v, OP_Column, iEphCur, 0, iKey);
+ }else{
+ sqlite3VdbeAddOp2(v, OP_RowData, iEphCur, iKey);
+ }
assert( nKey==0 ); /* OP_Found will use a composite key */
}else{
addrLoop = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, 0, iKey);
@@ -103735,12 +107127,8 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
#endif
{
int count = (pParse->nested==0); /* True to count changes */
- int iIdxNoSeek = -1;
- if( bComplex==0 && aiCurOnePass[1]!=iDataCur ){
- iIdxNoSeek = aiCurOnePass[1];
- }
sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
- iKey, nKey, count, OE_Default, eOnePass, iIdxNoSeek);
+ iKey, nKey, count, OE_Default, eOnePass, aiCurOnePass[1]);
}
/* End of the loop over all rowids/primary-keys. */
@@ -103754,14 +107142,6 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
sqlite3VdbeGoto(v, addrLoop);
sqlite3VdbeJumpHere(v, addrLoop);
}
-
- /* Close the cursors open on the table and its indexes. */
- if( !isView && !IsVirtual(pTab) ){
- if( !pPk ) sqlite3VdbeAddOp1(v, OP_Close, iDataCur);
- for(i=0, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
- sqlite3VdbeAddOp1(v, OP_Close, iIdxCur + i);
- }
- }
} /* End non-truncate path */
/* Update the sqlite_sequence table by storing the content of the
@@ -103786,6 +107166,10 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
sqlite3AuthContextPop(&sContext);
sqlite3SrcListDelete(db, pTabList);
sqlite3ExprDelete(db, pWhere);
+#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT)
+ sqlite3ExprListDelete(db, pOrderBy);
+ sqlite3ExprDelete(db, pLimit);
+#endif
sqlite3DbFree(db, aToOpen);
return;
}
@@ -103828,15 +107212,17 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
**
** If eMode is ONEPASS_MULTI, then this call is being made as part
** of a ONEPASS delete that affects multiple rows. In this case, if
-** iIdxNoSeek is a valid cursor number (>=0), then its position should
-** be preserved following the delete operation. Or, if iIdxNoSeek is not
-** a valid cursor number, the position of iDataCur should be preserved
-** instead.
+** iIdxNoSeek is a valid cursor number (>=0) and is not the same as
+** iDataCur, then its position should be preserved following the delete
+** operation. Or, if iIdxNoSeek is not a valid cursor number, the
+** position of iDataCur should be preserved instead.
**
** iIdxNoSeek:
-** If iIdxNoSeek is a valid cursor number (>=0), then it identifies an
-** index cursor (from within array of cursors starting at iIdxCur) that
-** already points to the index entry to be deleted.
+** If iIdxNoSeek is a valid cursor number (>=0) not equal to iDataCur,
+** then it identifies an index cursor (from within array of cursors
+** starting at iIdxCur) that already points to the index entry to be deleted.
+** Except, this optimization is disabled if there are BEFORE triggers since
+** the trigger body might have moved the cursor.
*/
SQLITE_PRIVATE void sqlite3GenerateRowDelete(
Parse *pParse, /* Parsing context */
@@ -103907,13 +107293,18 @@ SQLITE_PRIVATE void sqlite3GenerateRowDelete(
/* If any BEFORE triggers were coded, then seek the cursor to the
** row to be deleted again. It may be that the BEFORE triggers moved
- ** the cursor or of already deleted the row that the cursor was
+ ** the cursor or already deleted the row that the cursor was
** pointing to.
+ **
+ ** Also disable the iIdxNoSeek optimization since the BEFORE trigger
+ ** may have moved that cursor.
*/
if( addrStart=0 );
+ iIdxNoSeek = -1;
}
/* Do FK processing. This call checks that any FK constraints that
@@ -103936,11 +107327,13 @@ SQLITE_PRIVATE void sqlite3GenerateRowDelete(
u8 p5 = 0;
sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek);
sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0));
- sqlite3VdbeChangeP4(v, -1, (char*)pTab, P4_TABLE);
+ if( pParse->nested==0 || 0==sqlite3_stricmp(pTab->zName, "sqlite_stat1") ){
+ sqlite3VdbeAppendP4(v, (char*)pTab, P4_TABLE);
+ }
if( eMode!=ONEPASS_OFF ){
sqlite3VdbeChangeP5(v, OPFLAG_AUXDELETE);
}
- if( iIdxNoSeek>=0 ){
+ if( iIdxNoSeek>=0 && iIdxNoSeek!=iDataCur ){
sqlite3VdbeAddOp1(v, OP_Delete, iIdxNoSeek);
}
if( eMode==ONEPASS_MULTI ) p5 |= OPFLAG_SAVEPOSITION;
@@ -104064,10 +107457,11 @@ SQLITE_PRIVATE int sqlite3GenerateIndexKey(
if( piPartIdxLabel ){
if( pIdx->pPartIdxWhere ){
*piPartIdxLabel = sqlite3VdbeMakeLabel(v);
- pParse->iSelfTab = iDataCur;
+ pParse->iSelfTab = iDataCur + 1;
sqlite3ExprCachePush(pParse);
sqlite3ExprIfFalseDup(pParse, pIdx->pPartIdxWhere, *piPartIdxLabel,
SQLITE_JUMPIFNULL);
+ pParse->iSelfTab = 0;
}else{
*piPartIdxLabel = 0;
}
@@ -104094,6 +107488,10 @@ SQLITE_PRIVATE int sqlite3GenerateIndexKey(
}
if( regOut ){
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regOut);
+ if( pIdx->pTable->pSelect ){
+ const char *zAff = sqlite3IndexAffinityStr(pParse->db, pIdx);
+ sqlite3VdbeChangeP4(v, -1, zAff, P4_TRANSIENT);
+ }
}
sqlite3ReleaseTempRange(pParse, regBase, nCol);
return regBase;
@@ -104191,16 +107589,20 @@ static void typeofFunc(
int NotUsed,
sqlite3_value **argv
){
- const char *z = 0;
+ static const char *azType[] = { "integer", "real", "text", "blob", "null" };
+ int i = sqlite3_value_type(argv[0]) - 1;
UNUSED_PARAMETER(NotUsed);
- switch( sqlite3_value_type(argv[0]) ){
- case SQLITE_INTEGER: z = "integer"; break;
- case SQLITE_TEXT: z = "text"; break;
- case SQLITE_FLOAT: z = "real"; break;
- case SQLITE_BLOB: z = "blob"; break;
- default: z = "null"; break;
- }
- sqlite3_result_text(context, z, -1, SQLITE_STATIC);
+ assert( i>=0 && i0 ){
+ if( typeHaystack==SQLITE_BLOB && typeNeedle==SQLITE_BLOB ){
+ zHaystack = sqlite3_value_blob(argv[0]);
+ zNeedle = sqlite3_value_blob(argv[1]);
+ isText = 0;
+ }else{
+ zHaystack = sqlite3_value_text(argv[0]);
+ zNeedle = sqlite3_value_text(argv[1]);
+ isText = 1;
+ }
+ if( zNeedle==0 || (nHaystack && zHaystack==0) ) return;
+ while( nNeedle<=nHaystack && memcmp(zHaystack, zNeedle, nNeedle)!=0 ){
+ N++;
+ do{
+ nHaystack--;
+ zHaystack++;
+ }while( isText && (zHaystack[0]&0xc0)==0x80 );
+ }
+ if( nNeedle>nHaystack ) N = 0;
}
- if( nNeedle>nHaystack ) N = 0;
sqlite3_result_int(context, N);
}
@@ -104713,9 +108116,19 @@ static const struct compareInfo likeInfoNorm = { '%', '_', 0, 1 };
static const struct compareInfo likeInfoAlt = { '%', '_', 0, 0 };
/*
-** Compare two UTF-8 strings for equality where the first string can
-** potentially be a "glob" or "like" expression. Return true (1) if they
-** are the same and false (0) if they are different.
+** Possible error returns from patternMatch()
+*/
+#define SQLITE_MATCH 0
+#define SQLITE_NOMATCH 1
+#define SQLITE_NOWILDCARDMATCH 2
+
+/*
+** Compare two UTF-8 strings for equality where the first string is
+** a GLOB or LIKE expression. Return values:
+**
+** SQLITE_MATCH: Match
+** SQLITE_NOMATCH: No match
+** SQLITE_NOWILDCARDMATCH: No match in spite of having * or % wildcards.
**
** Globbing rules:
**
@@ -104766,30 +108179,31 @@ static int patternCompare(
** single character of the input string for each "?" skipped */
while( (c=Utf8Read(zPattern)) == matchAll || c == matchOne ){
if( c==matchOne && sqlite3Utf8Read(&zString)==0 ){
- return 0;
+ return SQLITE_NOWILDCARDMATCH;
}
}
if( c==0 ){
- return 1; /* "*" at the end of the pattern matches */
+ return SQLITE_MATCH; /* "*" at the end of the pattern matches */
}else if( c==matchOther ){
if( pInfo->matchSet==0 ){
c = sqlite3Utf8Read(&zPattern);
- if( c==0 ) return 0;
+ if( c==0 ) return SQLITE_NOWILDCARDMATCH;
}else{
/* "[...]" immediately follows the "*". We have to do a slow
** recursive search in this case, but it is an unusual case. */
assert( matchOther<0x80 ); /* '[' is a single-byte character */
- while( *zString
- && patternCompare(&zPattern[-1],zString,pInfo,matchOther)==0 ){
+ while( *zString ){
+ int bMatch = patternCompare(&zPattern[-1],zString,pInfo,matchOther);
+ if( bMatch!=SQLITE_NOMATCH ) return bMatch;
SQLITE_SKIP_UTF8(zString);
}
- return *zString!=0;
+ return SQLITE_NOWILDCARDMATCH;
}
}
/* At this point variable c contains the first character of the
** pattern string past the "*". Search in the input string for the
- ** first matching character and recursively contine the match from
+ ** first matching character and recursively continue the match from
** that point.
**
** For a case-insensitive search, set variable cx to be the same as
@@ -104797,36 +108211,44 @@ static int patternCompare(
** c or cx.
*/
if( c<=0x80 ){
- u32 cx;
+ char zStop[3];
+ int bMatch;
if( noCase ){
- cx = sqlite3Toupper(c);
- c = sqlite3Tolower(c);
+ zStop[0] = sqlite3Toupper(c);
+ zStop[1] = sqlite3Tolower(c);
+ zStop[2] = 0;
}else{
- cx = c;
+ zStop[0] = c;
+ zStop[1] = 0;
}
- while( (c2 = *(zString++))!=0 ){
- if( c2!=c && c2!=cx ) continue;
- if( patternCompare(zPattern,zString,pInfo,matchOther) ) return 1;
+ while(1){
+ zString += strcspn((const char*)zString, zStop);
+ if( zString[0]==0 ) break;
+ zString++;
+ bMatch = patternCompare(zPattern,zString,pInfo,matchOther);
+ if( bMatch!=SQLITE_NOMATCH ) return bMatch;
}
}else{
+ int bMatch;
while( (c2 = Utf8Read(zString))!=0 ){
if( c2!=c ) continue;
- if( patternCompare(zPattern,zString,pInfo,matchOther) ) return 1;
+ bMatch = patternCompare(zPattern,zString,pInfo,matchOther);
+ if( bMatch!=SQLITE_NOMATCH ) return bMatch;
}
}
- return 0;
+ return SQLITE_NOWILDCARDMATCH;
}
if( c==matchOther ){
if( pInfo->matchSet==0 ){
c = sqlite3Utf8Read(&zPattern);
- if( c==0 ) return 0;
+ if( c==0 ) return SQLITE_NOMATCH;
zEscaped = zPattern;
}else{
u32 prior_c = 0;
int seen = 0;
int invert = 0;
c = sqlite3Utf8Read(&zString);
- if( c==0 ) return 0;
+ if( c==0 ) return SQLITE_NOMATCH;
c2 = sqlite3Utf8Read(&zPattern);
if( c2=='^' ){
invert = 1;
@@ -104850,7 +108272,7 @@ static int patternCompare(
c2 = sqlite3Utf8Read(&zPattern);
}
if( c2==0 || (seen ^ invert)==0 ){
- return 0;
+ return SQLITE_NOMATCH;
}
continue;
}
@@ -104861,23 +108283,25 @@ static int patternCompare(
continue;
}
if( c==matchOne && zPattern!=zEscaped && c2!=0 ) continue;
- return 0;
+ return SQLITE_NOMATCH;
}
- return *zString==0;
+ return *zString==0 ? SQLITE_MATCH : SQLITE_NOMATCH;
}
/*
-** The sqlite3_strglob() interface.
+** The sqlite3_strglob() interface. Return 0 on a match (like strcmp()) and
+** non-zero if there is no match.
*/
SQLITE_API int sqlite3_strglob(const char *zGlobPattern, const char *zString){
- return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, '[')==0;
+ return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, '[');
}
/*
-** The sqlite3_strlike() interface.
+** The sqlite3_strlike() interface. Return 0 on a match and non-zero for
+** a miss - like strcmp().
*/
SQLITE_API int sqlite3_strlike(const char *zPattern, const char *zStr, unsigned int esc){
- return patternCompare((u8*)zPattern, (u8*)zStr, &likeInfoNorm, esc)==0;
+ return patternCompare((u8*)zPattern, (u8*)zStr, &likeInfoNorm, esc);
}
/*
@@ -104958,7 +108382,8 @@ static void likeFunc(
#ifdef SQLITE_TEST
sqlite3_like_count++;
#endif
- sqlite3_result_int(context, patternCompare(zB, zA, pInfo, escape));
+ sqlite3_result_int(context,
+ patternCompare(zB, zA, pInfo, escape)==SQLITE_MATCH);
}
}
@@ -105729,7 +109154,7 @@ static void groupConcatStep(
zSep = ",";
nSep = 1;
}
- if( nSep ) sqlite3StrAccumAppend(pAccum, zSep, nSep);
+ if( zSep ) sqlite3StrAccumAppend(pAccum, zSep, nSep);
}
zVal = (char*)sqlite3_value_text(argv[0]);
nVal = sqlite3_value_bytes(argv[0]);
@@ -105799,9 +109224,14 @@ SQLITE_PRIVATE void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive)
/*
** pExpr points to an expression which implements a function. If
** it is appropriate to apply the LIKE optimization to that function
-** then set aWc[0] through aWc[2] to the wildcard characters and
-** return TRUE. If the function is not a LIKE-style function then
-** return FALSE.
+** then set aWc[0] through aWc[2] to the wildcard characters and the
+** escape character and then return TRUE. If the function is not a
+** LIKE-style function then return FALSE.
+**
+** The expression "a LIKE b ESCAPE c" is only considered a valid LIKE
+** operator if c is a string literal that is exactly one byte in length.
+** That one byte is stored in aWc[3]. aWc[3] is set to zero if there is
+** no ESCAPE clause.
**
** *pIsNocase is set to true if uppercase and lowercase are equivalent for
** the function (default for LIKE). If the function makes the distinction
@@ -105810,17 +109240,26 @@ SQLITE_PRIVATE void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive)
*/
SQLITE_PRIVATE int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
FuncDef *pDef;
- if( pExpr->op!=TK_FUNCTION
- || !pExpr->x.pList
- || pExpr->x.pList->nExpr!=2
- ){
+ int nExpr;
+ if( pExpr->op!=TK_FUNCTION || !pExpr->x.pList ){
return 0;
}
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
- pDef = sqlite3FindFunction(db, pExpr->u.zToken, 2, SQLITE_UTF8, 0);
+ nExpr = pExpr->x.pList->nExpr;
+ pDef = sqlite3FindFunction(db, pExpr->u.zToken, nExpr, SQLITE_UTF8, 0);
if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_FUNC_LIKE)==0 ){
return 0;
}
+ if( nExpr<3 ){
+ aWc[3] = 0;
+ }else{
+ Expr *pEscape = pExpr->x.pList->a[2].pExpr;
+ char *zEscape;
+ if( pEscape->op!=TK_STRING ) return 0;
+ zEscape = pEscape->u.zToken;
+ if( zEscape[0]==0 || zEscape[1]!=0 ) return 0;
+ aWc[3] = zEscape[0];
+ }
/* The memcpy() statement assumes that the wildcard characters are
** the first three statements in the compareInfo structure. The
@@ -105870,6 +109309,13 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){
FUNCTION2(unlikely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
FUNCTION2(likelihood, 2, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
FUNCTION2(likely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
+#ifdef SQLITE_DEBUG
+ FUNCTION2(affinity, 1, 0, 0, noopFunc, SQLITE_FUNC_AFFINITY),
+#endif
+#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
+ FUNCTION2(sqlite_offset, 1, 0, 0, noopFunc, SQLITE_FUNC_OFFSET|
+ SQLITE_FUNC_TYPEOF),
+#endif
FUNCTION(ltrim, 1, 1, 0, trimFunc ),
FUNCTION(ltrim, 2, 1, 0, trimFunc ),
FUNCTION(rtrim, 1, 2, 0, trimFunc ),
@@ -106192,7 +109638,7 @@ SQLITE_PRIVATE int sqlite3FkLocateIndex(
}
for(pIdx=pParent->pIndex; pIdx; pIdx=pIdx->pNext){
- if( pIdx->nKeyCol==nCol && IsUniqueIndex(pIdx) ){
+ if( pIdx->nKeyCol==nCol && IsUniqueIndex(pIdx) && pIdx->pPartIdxWhere==0 ){
/* pIdx is a UNIQUE index (or a PRIMARY KEY) and has the right number
** of columns. If each indexed column corresponds to a foreign key
** column of pFKey, then this index is a winner. */
@@ -106551,7 +109997,7 @@ static void fkScanChildren(
assert( iCol>=0 );
zCol = pFKey->pFrom->aCol[iCol].zName;
pRight = sqlite3Expr(db, TK_ID, zCol);
- pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight, 0);
+ pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight);
pWhere = sqlite3ExprAnd(db, pWhere, pEq);
}
@@ -106573,7 +110019,7 @@ static void fkScanChildren(
if( HasRowid(pTab) ){
pLeft = exprTableRegister(pParse, pTab, regData, -1);
pRight = exprTableColumn(db, pTab, pSrc->a[0].iCursor, -1);
- pNe = sqlite3PExpr(pParse, TK_NE, pLeft, pRight, 0);
+ pNe = sqlite3PExpr(pParse, TK_NE, pLeft, pRight);
}else{
Expr *pEq, *pAll = 0;
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
@@ -106583,10 +110029,10 @@ static void fkScanChildren(
assert( iCol>=0 );
pLeft = exprTableRegister(pParse, pTab, regData, iCol);
pRight = exprTableColumn(db, pTab, pSrc->a[0].iCursor, iCol);
- pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight, 0);
+ pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight);
pAll = sqlite3ExprAnd(db, pAll, pEq);
}
- pNe = sqlite3PExpr(pParse, TK_NOT, pAll, 0, 0);
+ pNe = sqlite3PExpr(pParse, TK_NOT, pAll, 0);
}
pWhere = sqlite3ExprAnd(db, pWhere, pNe);
}
@@ -106600,10 +110046,12 @@ static void fkScanChildren(
/* Create VDBE to loop through the entries in pSrc that match the WHERE
** clause. For each row found, increment either the deferred or immediate
** foreign key constraint counter. */
- pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0);
- sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
- if( pWInfo ){
- sqlite3WhereEnd(pWInfo);
+ if( pParse->nErr==0 ){
+ pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0);
+ sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
+ if( pWInfo ){
+ sqlite3WhereEnd(pWInfo);
+ }
}
/* Clean up the WHERE clause constructed above. */
@@ -106690,7 +110138,7 @@ SQLITE_PRIVATE void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTa
}
pParse->disableTriggers = 1;
- sqlite3DeleteFrom(pParse, sqlite3SrcListDup(db, pName, 0), 0);
+ sqlite3DeleteFrom(pParse, sqlite3SrcListDup(db, pName, 0), 0, 0, 0);
pParse->disableTriggers = 0;
/* If the DELETE has generated immediate foreign key constraint
@@ -106974,7 +110422,7 @@ SQLITE_PRIVATE void sqlite3FkCheck(
struct SrcList_item *pItem = pSrc->a;
pItem->pTab = pFKey->pFrom;
pItem->zName = pFKey->pFrom->zName;
- pItem->pTab->nRef++;
+ pItem->pTab->nTabRef++;
pItem->iCursor = pParse->nTab++;
if( regNew!=0 ){
@@ -107054,8 +110502,16 @@ SQLITE_PRIVATE u32 sqlite3FkOldmask(
** UPDATE statement modifies the rowid fields of the table.
**
** If any foreign key processing will be required, this function returns
-** true. If there is no foreign key related processing, this function
-** returns false.
+** non-zero. If there is no foreign key related processing, this function
+** returns zero.
+**
+** For an UPDATE, this function returns 2 if:
+**
+** * There are any FKs for which pTab is the child and the parent table, or
+** * the UPDATE modifies one or more parent keys for which the action is
+** not "NO ACTION" (i.e. is CASCADE, SET DEFAULT or SET NULL).
+**
+** Or, assuming some other foreign key processing is required, 1.
*/
SQLITE_PRIVATE int sqlite3FkRequired(
Parse *pParse, /* Parse context */
@@ -107063,12 +110519,13 @@ SQLITE_PRIVATE int sqlite3FkRequired(
int *aChange, /* Non-NULL for UPDATE operations */
int chngRowid /* True for UPDATE that affects rowid */
){
+ int eRet = 0;
if( pParse->db->flags&SQLITE_ForeignKeys ){
if( !aChange ){
/* A DELETE operation. Foreign key processing is required if the
** table in question is either the child or parent table for any
** foreign key constraint. */
- return (sqlite3FkReferences(pTab) || pTab->pFKey);
+ eRet = (sqlite3FkReferences(pTab) || pTab->pFKey);
}else{
/* This is an UPDATE. Foreign key processing is only required if the
** operation modifies one or more child or parent key columns. */
@@ -107076,16 +110533,22 @@ SQLITE_PRIVATE int sqlite3FkRequired(
/* Check if any child key columns are being modified. */
for(p=pTab->pFKey; p; p=p->pNextFrom){
- if( fkChildIsModified(pTab, p, aChange, chngRowid) ) return 1;
+ if( 0==sqlite3_stricmp(pTab->zName, p->zTo) ) return 2;
+ if( fkChildIsModified(pTab, p, aChange, chngRowid) ){
+ eRet = 1;
+ }
}
/* Check if any parent key columns are being modified. */
for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){
- if( fkParentIsModified(pTab, p, aChange, chngRowid) ) return 1;
+ if( fkParentIsModified(pTab, p, aChange, chngRowid) ){
+ if( p->aAction[1]!=OE_None ) return 2;
+ eRet = 1;
+ }
}
}
}
- return 0;
+ return eRet;
}
/*
@@ -107172,10 +110635,9 @@ static Trigger *fkActionTrigger(
pEq = sqlite3PExpr(pParse, TK_EQ,
sqlite3PExpr(pParse, TK_DOT,
sqlite3ExprAlloc(db, TK_ID, &tOld, 0),
- sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)
- , 0),
+ sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)),
sqlite3ExprAlloc(db, TK_ID, &tFromCol, 0)
- , 0);
+ );
pWhere = sqlite3ExprAnd(db, pWhere, pEq);
/* For ON UPDATE, construct the next term of the WHEN clause.
@@ -107187,13 +110649,11 @@ static Trigger *fkActionTrigger(
pEq = sqlite3PExpr(pParse, TK_IS,
sqlite3PExpr(pParse, TK_DOT,
sqlite3ExprAlloc(db, TK_ID, &tOld, 0),
- sqlite3ExprAlloc(db, TK_ID, &tToCol, 0),
- 0),
+ sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)),
sqlite3PExpr(pParse, TK_DOT,
sqlite3ExprAlloc(db, TK_ID, &tNew, 0),
- sqlite3ExprAlloc(db, TK_ID, &tToCol, 0),
- 0),
- 0);
+ sqlite3ExprAlloc(db, TK_ID, &tToCol, 0))
+ );
pWhen = sqlite3ExprAnd(db, pWhen, pEq);
}
@@ -107202,8 +110662,7 @@ static Trigger *fkActionTrigger(
if( action==OE_Cascade ){
pNew = sqlite3PExpr(pParse, TK_DOT,
sqlite3ExprAlloc(db, TK_ID, &tNew, 0),
- sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)
- , 0);
+ sqlite3ExprAlloc(db, TK_ID, &tToCol, 0));
}else if( action==OE_SetDflt ){
Expr *pDflt = pFKey->pFrom->aCol[iFromCol].pDflt;
if( pDflt ){
@@ -107237,7 +110696,7 @@ static Trigger *fkActionTrigger(
sqlite3ExprListAppend(pParse, 0, pRaise),
sqlite3SrcListAppend(db, 0, &tFrom, 0),
pWhere,
- 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0
);
pWhere = 0;
}
@@ -107259,7 +110718,7 @@ static Trigger *fkActionTrigger(
pStep->pExprList = sqlite3ExprListDup(db, pList, EXPRDUP_REDUCE);
pStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
if( pWhen ){
- pWhen = sqlite3PExpr(pParse, TK_NOT, pWhen, 0, 0);
+ pWhen = sqlite3PExpr(pParse, TK_NOT, pWhen, 0);
pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE);
}
}
@@ -107604,7 +111063,7 @@ static int autoIncBegin(
){
int memId = 0; /* Register holding maximum rowid */
if( (pTab->tabFlags & TF_Autoincrement)!=0
- && (pParse->db->flags & SQLITE_Vacuum)==0
+ && (pParse->db->mDbFlags & DBFLAG_Vacuum)==0
){
Parse *pToplevel = sqlite3ParseToplevel(pParse);
AutoincInfo *pInfo;
@@ -107862,8 +111321,7 @@ SQLITE_PRIVATE void sqlite3Insert(
){
sqlite3 *db; /* The main database structure */
Table *pTab; /* The table to insert into. aka TABLE */
- char *zTab; /* Name of the table into which we are inserting */
- int i, j, idx; /* Loop counters */
+ int i, j; /* Loop counters */
Vdbe *v; /* Generate code into this virtual machine */
Index *pIdx; /* For looping over indices of the table */
int nColumn; /* Number of columns in the data */
@@ -107899,10 +111357,10 @@ SQLITE_PRIVATE void sqlite3Insert(
#endif
db = pParse->db;
- memset(&dest, 0, sizeof(dest));
if( pParse->nErr || db->mallocFailed ){
goto insert_cleanup;
}
+ dest.iSDParm = 0; /* Suppress a harmless compiler warning */
/* If the Select object is really just a simple VALUES() list with a
** single row (the common case) then keep that one row of values
@@ -107918,8 +111376,6 @@ SQLITE_PRIVATE void sqlite3Insert(
/* Locate the table into which we will be inserting new information.
*/
assert( pTabList->nSrc==1 );
- zTab = pTabList->a[0].zName;
- if( NEVER(zTab==0) ) goto insert_cleanup;
pTab = sqlite3SrcListLookup(pParse, pTabList);
if( pTab==0 ){
goto insert_cleanup;
@@ -108170,8 +111626,10 @@ SQLITE_PRIVATE void sqlite3Insert(
if( aRegIdx==0 ){
goto insert_cleanup;
}
- for(i=0; ipIndex; ipNext, i++){
+ assert( pIdx );
aRegIdx[i] = ++pParse->nMem;
+ pParse->nMem += pIdx->nColumn;
}
}
@@ -108288,7 +111746,8 @@ SQLITE_PRIVATE void sqlite3Insert(
VdbeOp *pOp;
sqlite3ExprCode(pParse, pList->a[ipkColumn].pExpr, regRowid);
pOp = sqlite3VdbeGetOp(v, -1);
- if( ALWAYS(pOp) && pOp->opcode==OP_Null && !IsVirtual(pTab) ){
+ assert( pOp!=0 );
+ if( pOp->opcode==OP_Null && !IsVirtual(pTab) ){
appendFlag = 1;
pOp->opcode = OP_NewRowid;
pOp->p1 = iDataCur;
@@ -108373,12 +111832,26 @@ SQLITE_PRIVATE void sqlite3Insert(
#endif
{
int isReplace; /* Set to true if constraints may cause a replace */
+ int bUseSeek; /* True to use OPFLAG_SEEKRESULT */
sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur,
regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace, 0
);
sqlite3FkCheck(pParse, pTab, 0, regIns, 0, 0);
+
+ /* Set the OPFLAG_USESEEKRESULT flag if either (a) there are no REPLACE
+ ** constraints or (b) there are no triggers and this table is not a
+ ** parent table in a foreign key constraint. It is safe to set the
+ ** flag in the second case as if any REPLACE constraint is hit, an
+ ** OP_Delete or OP_IdxDelete instruction will be executed on each
+ ** cursor that is disturbed. And these instructions both clear the
+ ** VdbeCursor.seekResult variable, disabling the OPFLAG_USESEEKRESULT
+ ** functionality. */
+ bUseSeek = (isReplace==0 || (pTrigger==0 &&
+ ((db->flags & SQLITE_ForeignKeys)==0 || sqlite3FkReferences(pTab)==0)
+ ));
sqlite3CompleteInsertion(pParse, pTab, iDataCur, iIdxCur,
- regIns, aRegIdx, 0, appendFlag, isReplace==0);
+ regIns, aRegIdx, 0, appendFlag, bUseSeek
+ );
}
}
@@ -108407,14 +111880,6 @@ SQLITE_PRIVATE void sqlite3Insert(
sqlite3VdbeJumpHere(v, addrInsTop);
}
- if( !IsVirtual(pTab) && !isView ){
- /* Close all tables opened */
- if( iDataCurpIndex; pIdx; pIdx=pIdx->pNext, idx++){
- sqlite3VdbeAddOp1(v, OP_Close, idx+iIdxCur);
- }
- }
-
insert_end:
/* Update the sqlite_sequence table by storing the content of the
** maximum rowid counter values recorded while inserting into
@@ -108621,7 +112086,6 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
int ipkBottom = 0; /* Bottom of the rowid change constraint check */
u8 isUpdate; /* True if this is an UPDATE operation */
u8 bAffinityDone = 0; /* True if the OP_Affinity operation has been run */
- int regRowid = -1; /* Register holding ROWID value */
isUpdate = regOldData!=0;
db = pParse->db;
@@ -108676,8 +112140,9 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
case OE_Fail: {
char *zMsg = sqlite3MPrintf(db, "%s.%s", pTab->zName,
pTab->aCol[i].zName);
- sqlite3VdbeAddOp4(v, OP_HaltIfNull, SQLITE_CONSTRAINT_NOTNULL, onError,
- regNewData+1+i, zMsg, P4_DYNAMIC);
+ sqlite3VdbeAddOp3(v, OP_HaltIfNull, SQLITE_CONSTRAINT_NOTNULL, onError,
+ regNewData+1+i);
+ sqlite3VdbeAppendP4(v, zMsg, P4_DYNAMIC);
sqlite3VdbeChangeP5(v, P5_ConstraintNotNull);
VdbeCoverage(v);
break;
@@ -108703,7 +112168,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
#ifndef SQLITE_OMIT_CHECK
if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){
ExprList *pCheck = pTab->pCheck;
- pParse->ckBase = regNewData+1;
+ pParse->iSelfTab = -(regNewData+1);
onError = overrideError!=OE_Default ? overrideError : OE_Abort;
for(i=0; inExpr; i++){
int allOk;
@@ -108723,6 +112188,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
}
sqlite3VdbeResolveLabel(v, allOk);
}
+ pParse->iSelfTab = 0;
}
#endif /* !defined(SQLITE_OMIT_CHECK) */
@@ -108741,7 +112207,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
}
if( isUpdate ){
- /* pkChng!=0 does not mean that the rowid has change, only that
+ /* pkChng!=0 does not mean that the rowid has changed, only that
** it might have changed. Skip the conflict logic below if the rowid
** is unchanged. */
sqlite3VdbeAddOp3(v, OP_Eq, regNewData, addrRowidOk, regOldData);
@@ -108819,7 +112285,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
** OP_Insert replace the existing entry than it is to delete the
** existing entry and then insert a new one. */
sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, OPFLAG_ISNOOP);
- sqlite3VdbeChangeP4(v, -1, (char *)pTab, P4_TABLE);
+ sqlite3VdbeAppendP4(v, pTab, P4_TABLE);
}
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
if( pTab->pIndex ){
@@ -108867,29 +112333,27 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
/* Skip partial indices for which the WHERE clause is not true */
if( pIdx->pPartIdxWhere ){
sqlite3VdbeAddOp2(v, OP_Null, 0, aRegIdx[ix]);
- pParse->ckBase = regNewData+1;
+ pParse->iSelfTab = -(regNewData+1);
sqlite3ExprIfFalseDup(pParse, pIdx->pPartIdxWhere, addrUniqueOk,
SQLITE_JUMPIFNULL);
- pParse->ckBase = 0;
+ pParse->iSelfTab = 0;
}
/* Create a record for this index entry as it should appear after
** the insert or update. Store that record in the aRegIdx[ix] register
*/
- regIdx = sqlite3GetTempRange(pParse, pIdx->nColumn);
+ regIdx = aRegIdx[ix]+1;
for(i=0; inColumn; i++){
int iField = pIdx->aiColumn[i];
int x;
if( iField==XN_EXPR ){
- pParse->ckBase = regNewData+1;
+ pParse->iSelfTab = -(regNewData+1);
sqlite3ExprCodeCopy(pParse, pIdx->aColExpr->a[i].pExpr, regIdx+i);
- pParse->ckBase = 0;
+ pParse->iSelfTab = 0;
VdbeComment((v, "%s column %d", pIdx->zName, i));
}else{
if( iField==XN_ROWID || iField==pTab->iPKey ){
- if( regRowid==regIdx+i ) continue; /* ROWID already in regIdx+i */
x = regNewData;
- regRowid = pIdx->pPartIdxWhere ? -1 : regIdx+i;
}else{
x = iField + regNewData + 1;
}
@@ -108899,7 +112363,9 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
}
sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn, aRegIdx[ix]);
VdbeComment((v, "for %s", pIdx->zName));
- sqlite3ExprCacheAffinityChange(pParse, regIdx, pIdx->nColumn);
+#ifdef SQLITE_ENABLE_NULL_TRIM
+ if( pIdx->idxType==2 ) sqlite3SetMakeRecordP5(v, pIdx->pTable);
+#endif
/* In an UPDATE operation, if this index is the PRIMARY KEY index
** of a WITHOUT ROWID table and there has been no change the
@@ -108913,7 +112379,6 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
/* Find out what action to take in case there is a uniqueness conflict */
onError = pIdx->onError;
if( onError==OE_None ){
- sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn);
sqlite3VdbeResolveLabel(v, addrUniqueOk);
continue; /* pIdx is not a UNIQUE index */
}
@@ -108922,8 +112387,28 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
}else if( onError==OE_Default ){
onError = OE_Abort;
}
-
+
+ /* Collision detection may be omitted if all of the following are true:
+ ** (1) The conflict resolution algorithm is REPLACE
+ ** (2) The table is a WITHOUT ROWID table
+ ** (3) There are no secondary indexes on the table
+ ** (4) No delete triggers need to be fired if there is a conflict
+ ** (5) No FK constraint counters need to be updated if a conflict occurs.
+ */
+ if( (ix==0 && pIdx->pNext==0) /* Condition 3 */
+ && pPk==pIdx /* Condition 2 */
+ && onError==OE_Replace /* Condition 1 */
+ && ( 0==(db->flags&SQLITE_RecTriggers) || /* Condition 4 */
+ 0==sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0))
+ && ( 0==(db->flags&SQLITE_ForeignKeys) || /* Condition 5 */
+ (0==pTab->pFKey && 0==sqlite3FkReferences(pTab)))
+ ){
+ sqlite3VdbeResolveLabel(v, addrUniqueOk);
+ continue;
+ }
+
/* Check to see if the new index entry will be unique */
+ sqlite3ExprCachePush(pParse);
sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk,
regIdx, pIdx->nKeyCol); VdbeCoverage(v);
@@ -109006,13 +112491,13 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
}
sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
regR, nPkField, 0, OE_Replace,
- (pIdx==pPk ? ONEPASS_SINGLE : ONEPASS_OFF), -1);
+ (pIdx==pPk ? ONEPASS_SINGLE : ONEPASS_OFF), iThisCur);
seenReplace = 1;
break;
}
}
sqlite3VdbeResolveLabel(v, addrUniqueOk);
- sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn);
+ sqlite3ExprCachePop(pParse);
if( regR!=regIdx ) sqlite3ReleaseTempRange(pParse, regR, nPkField);
}
if( ipkTop ){
@@ -109024,6 +112509,28 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
VdbeModuleComment((v, "END: GenCnstCks(%d)", seenReplace));
}
+#ifdef SQLITE_ENABLE_NULL_TRIM
+/*
+** Change the P5 operand on the last opcode (which should be an OP_MakeRecord)
+** to be the number of columns in table pTab that must not be NULL-trimmed.
+**
+** Or if no columns of pTab may be NULL-trimmed, leave P5 at zero.
+*/
+SQLITE_PRIVATE void sqlite3SetMakeRecordP5(Vdbe *v, Table *pTab){
+ u16 i;
+
+ /* Records with omitted columns are only allowed for schema format
+ ** version 2 and later (SQLite version 3.1.4, 2005-02-20). */
+ if( pTab->pSchema->file_format<2 ) return;
+
+ for(i=pTab->nCol-1; i>0; i--){
+ if( pTab->aCol[i].pDflt!=0 ) break;
+ if( pTab->aCol[i].colFlags & COLFLAG_PRIMKEY ) break;
+ }
+ sqlite3VdbeChangeP5(v, i+1);
+}
+#endif
+
/*
** This routine generates code to finish the INSERT or UPDATE operation
** that was started by a prior call to sqlite3GenerateConstraintChecks.
@@ -109040,7 +112547,7 @@ SQLITE_PRIVATE void sqlite3CompleteInsertion(
int iIdxCur, /* First index cursor */
int regNewData, /* Range of content */
int *aRegIdx, /* Register used by each index. 0 for unused indices */
- int isUpdate, /* True for UPDATE, False for INSERT */
+ int update_flags, /* True for UPDATE, False for INSERT */
int appendBias, /* True if this is likely to be an append */
int useSeekResult /* True to set the USESEEKRESULT flag on OP_[Idx]Insert */
){
@@ -109052,6 +112559,11 @@ SQLITE_PRIVATE void sqlite3CompleteInsertion(
int i; /* Loop counter */
u8 bAffinityDone = 0; /* True if OP_Affinity has been run already */
+ assert( update_flags==0
+ || update_flags==OPFLAG_ISUPDATE
+ || update_flags==(OPFLAG_ISUPDATE|OPFLAG_SAVEPOSITION)
+ );
+
v = sqlite3GetVdbe(pParse);
assert( v!=0 );
assert( pTab->pSelect==0 ); /* This table is not a VIEW */
@@ -109062,26 +112574,39 @@ SQLITE_PRIVATE void sqlite3CompleteInsertion(
sqlite3VdbeAddOp2(v, OP_IsNull, aRegIdx[i], sqlite3VdbeCurrentAddr(v)+2);
VdbeCoverage(v);
}
- sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i]);
- pik_flags = 0;
- if( useSeekResult ) pik_flags = OPFLAG_USESEEKRESULT;
+ pik_flags = (useSeekResult ? OPFLAG_USESEEKRESULT : 0);
if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
assert( pParse->nested==0 );
pik_flags |= OPFLAG_NCHANGE;
+ pik_flags |= (update_flags & OPFLAG_SAVEPOSITION);
+#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
+ if( update_flags==0 ){
+ sqlite3VdbeAddOp4(v, OP_InsertInt,
+ iIdxCur+i, aRegIdx[i], 0, (char*)pTab, P4_TABLE
+ );
+ sqlite3VdbeChangeP5(v, OPFLAG_ISNOOP);
+ }
+#endif
}
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i],
+ aRegIdx[i]+1,
+ pIdx->uniqNotNull ? pIdx->nKeyCol: pIdx->nColumn);
sqlite3VdbeChangeP5(v, pik_flags);
}
if( !HasRowid(pTab) ) return;
regData = regNewData + 1;
regRec = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec);
- if( !bAffinityDone ) sqlite3TableAffinity(v, pTab, 0);
- sqlite3ExprCacheAffinityChange(pParse, regData, pTab->nCol);
+ sqlite3SetMakeRecordP5(v, pTab);
+ if( !bAffinityDone ){
+ sqlite3TableAffinity(v, pTab, 0);
+ sqlite3ExprCacheAffinityChange(pParse, regData, pTab->nCol);
+ }
if( pParse->nested ){
pik_flags = 0;
}else{
pik_flags = OPFLAG_NCHANGE;
- pik_flags |= (isUpdate?OPFLAG_ISUPDATE:OPFLAG_LASTROWID);
+ pik_flags |= (update_flags?update_flags:OPFLAG_LASTROWID);
}
if( appendBias ){
pik_flags |= OPFLAG_APPEND;
@@ -109091,7 +112616,7 @@ SQLITE_PRIVATE void sqlite3CompleteInsertion(
}
sqlite3VdbeAddOp3(v, OP_Insert, iDataCur, regRec, regNewData);
if( !pParse->nested ){
- sqlite3VdbeChangeP4(v, -1, (char *)pTab, P4_TABLE);
+ sqlite3VdbeAppendP4(v, pTab, P4_TABLE);
}
sqlite3VdbeChangeP5(v, pik_flags);
}
@@ -109211,7 +112736,7 @@ static int xferCompatibleIndex(Index *pDest, Index *pSrc){
}
if( pSrc->aiColumn[i]==XN_EXPR ){
assert( pSrc->aColExpr!=0 && pDest->aColExpr!=0 );
- if( sqlite3ExprCompare(pSrc->aColExpr->a[i].pExpr,
+ if( sqlite3ExprCompare(0, pSrc->aColExpr->a[i].pExpr,
pDest->aColExpr->a[i].pExpr, -1)!=0 ){
return 0; /* Different expressions in the index */
}
@@ -109223,7 +112748,7 @@ static int xferCompatibleIndex(Index *pDest, Index *pSrc){
return 0; /* Different collating sequences */
}
}
- if( sqlite3ExprCompare(pSrc->pPartIdxWhere, pDest->pPartIdxWhere, -1) ){
+ if( sqlite3ExprCompare(0, pSrc->pPartIdxWhere, pDest->pPartIdxWhere, -1) ){
return 0; /* Different WHERE clauses */
}
@@ -109292,7 +112817,7 @@ static int xferOptimization(
return 0; /* tab1 must not have triggers */
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( pDest->tabFlags & TF_Virtual ){
+ if( IsVirtual(pDest) ){
return 0; /* tab1 must not be a virtual table */
}
#endif
@@ -109321,7 +112846,6 @@ static int xferOptimization(
if( pSelect->pLimit ){
return 0; /* SELECT may not have a LIMIT clause */
}
- assert( pSelect->pOffset==0 ); /* Must be so if pLimit==0 */
if( pSelect->pPrior ){
return 0; /* SELECT may not be a compound query */
}
@@ -109354,7 +112878,7 @@ static int xferOptimization(
return 0; /* source and destination must both be WITHOUT ROWID or not */
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( pSrc->tabFlags & TF_Virtual ){
+ if( IsVirtual(pSrc) ){
return 0; /* tab2 must not be a virtual table */
}
#endif
@@ -109371,7 +112895,7 @@ static int xferOptimization(
Column *pDestCol = &pDest->aCol[i];
Column *pSrcCol = &pSrc->aCol[i];
#ifdef SQLITE_ENABLE_HIDDEN_COLUMNS
- if( (db->flags & SQLITE_Vacuum)==0
+ if( (db->mDbFlags & DBFLAG_Vacuum)==0
&& (pDestCol->colFlags | pSrcCol->colFlags) & COLFLAG_HIDDEN
){
return 0; /* Neither table may have __hidden__ columns */
@@ -109447,15 +112971,15 @@ static int xferOptimization(
regRowid = sqlite3GetTempReg(pParse);
sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite);
assert( HasRowid(pDest) || destHasUniqueIdx );
- if( (db->flags & SQLITE_Vacuum)==0 && (
+ if( (db->mDbFlags & DBFLAG_Vacuum)==0 && (
(pDest->iPKey<0 && pDest->pIndex!=0) /* (1) */
|| destHasUniqueIdx /* (2) */
|| (onError!=OE_Abort && onError!=OE_Rollback) /* (3) */
)){
/* In some circumstances, we are able to run the xfer optimization
** only if the destination table is initially empty. Unless the
- ** SQLITE_Vacuum flag is set, this block generates code to make
- ** that determination. If SQLITE_Vacuum is set, then the destination
+ ** DBFLAG_Vacuum flag is set, this block generates code to make
+ ** that determination. If DBFLAG_Vacuum is set, then the destination
** table is always empty.
**
** Conditions under which the destination must be empty:
@@ -109474,6 +112998,7 @@ static int xferOptimization(
sqlite3VdbeJumpHere(v, addr1);
}
if( HasRowid(pSrc) ){
+ u8 insFlags;
sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead);
emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v);
if( pDest->iPKey>=0 ){
@@ -109489,10 +113014,17 @@ static int xferOptimization(
addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
assert( (pDest->tabFlags & TF_Autoincrement)==0 );
}
- sqlite3VdbeAddOp2(v, OP_RowData, iSrc, regData);
+ sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
+ if( db->mDbFlags & DBFLAG_Vacuum ){
+ sqlite3VdbeAddOp1(v, OP_SeekEnd, iDest);
+ insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID|
+ OPFLAG_APPEND|OPFLAG_USESEEKRESULT;
+ }else{
+ insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND;
+ }
sqlite3VdbeAddOp4(v, OP_Insert, iDest, regData, regRowid,
(char*)pDest, P4_TABLE);
- sqlite3VdbeChangeP5(v, OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND);
+ sqlite3VdbeChangeP5(v, insFlags);
sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0);
sqlite3VdbeAddOp2(v, OP_Close, iDest, 0);
@@ -109514,14 +113046,14 @@ static int xferOptimization(
sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR);
VdbeComment((v, "%s", pDestIdx->zName));
addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v);
- sqlite3VdbeAddOp2(v, OP_RowKey, iSrc, regData);
- if( db->flags & SQLITE_Vacuum ){
+ sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
+ if( db->mDbFlags & DBFLAG_Vacuum ){
/* This INSERT command is part of a VACUUM operation, which guarantees
** that the destination table is empty. If all indexed columns use
** collation sequence BINARY, then it can also be assumed that the
** index will be populated by inserting keys in strictly sorted
** order. In this case, instead of seeking within the b-tree as part
- ** of every OP_IdxInsert opcode, an OP_Last is added before the
+ ** of every OP_IdxInsert opcode, an OP_SeekEnd is added before the
** OP_IdxInsert to seek to the point within the b-tree where each key
** should be inserted. This is faster.
**
@@ -109532,20 +113064,18 @@ static int xferOptimization(
** sorted order. */
for(i=0; inColumn; i++){
const char *zColl = pSrcIdx->azColl[i];
- assert( sqlite3_stricmp(sqlite3StrBINARY, zColl)!=0
- || sqlite3StrBINARY==zColl );
if( sqlite3_stricmp(sqlite3StrBINARY, zColl) ) break;
}
if( i==pSrcIdx->nColumn ){
idxInsFlags = OPFLAG_USESEEKRESULT;
- sqlite3VdbeAddOp3(v, OP_Last, iDest, 0, -1);
+ sqlite3VdbeAddOp1(v, OP_SeekEnd, iDest);
}
}
if( !HasRowid(pSrc) && pDestIdx->idxType==2 ){
idxInsFlags |= OPFLAG_NCHANGE;
}
- sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, regData, 1);
- sqlite3VdbeChangeP5(v, idxInsFlags);
+ sqlite3VdbeAddOp2(v, OP_IdxInsert, iDest, regData);
+ sqlite3VdbeChangeP5(v, idxInsFlags|OPFLAG_APPEND);
sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, addr1);
sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0);
@@ -109643,7 +113173,7 @@ SQLITE_API int sqlite3_exec(
(SQLITE_DONE==rc && !callbackIsInit
&& db->flags&SQLITE_NullCallback)) ){
if( !callbackIsInit ){
- azCols = sqlite3DbMallocZero(db, 2*nCol*sizeof(const char*) + 1);
+ azCols = sqlite3DbMallocRaw(db, (2*nCol+1)*sizeof(const char*));
if( azCols==0 ){
goto exec_out;
}
@@ -109664,6 +113194,7 @@ SQLITE_API int sqlite3_exec(
goto exec_out;
}
}
+ azVals[i] = 0;
}
if( xCallback(pArg, nCol, azVals, azCols) ){
/* EVIDENCE-OF: R-38229-40159 If the callback function to
@@ -109696,11 +113227,8 @@ SQLITE_API int sqlite3_exec(
rc = sqlite3ApiExit(db, rc);
if( rc!=SQLITE_OK && pzErrMsg ){
- int nErrMsg = 1 + sqlite3Strlen30(sqlite3_errmsg(db));
- *pzErrMsg = sqlite3Malloc(nErrMsg);
- if( *pzErrMsg ){
- memcpy(*pzErrMsg, sqlite3_errmsg(db), nErrMsg);
- }else{
+ *pzErrMsg = sqlite3DbStrDup(0, sqlite3_errmsg(db));
+ if( *pzErrMsg==0 ){
rc = SQLITE_NOMEM_BKPT;
sqlite3Error(db, SQLITE_NOMEM);
}
@@ -109871,7 +113399,7 @@ struct sqlite3_api_routines {
int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,
const char*,const char*),void*);
void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*));
- char * (*snprintf)(int,char*,const char*,...);
+ char * (*xsnprintf)(int,char*,const char*,...);
int (*step)(sqlite3_stmt*);
int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,
char const**,char const**,int*,int*,int*);
@@ -109983,7 +113511,7 @@ struct sqlite3_api_routines {
int (*uri_boolean)(const char*,const char*,int);
sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64);
const char *(*uri_parameter)(const char*,const char*);
- char *(*vsnprintf)(int,char*,const char*,va_list);
+ char *(*xvsnprintf)(int,char*,const char*,va_list);
int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*);
/* Version 3.8.7 and later */
int (*auto_extension)(void(*)(void));
@@ -110019,6 +113547,19 @@ struct sqlite3_api_routines {
/* Version 3.14.0 and later */
int (*trace_v2)(sqlite3*,unsigned,int(*)(unsigned,void*,void*,void*),void*);
char *(*expanded_sql)(sqlite3_stmt*);
+ /* Version 3.18.0 and later */
+ void (*set_last_insert_rowid)(sqlite3*,sqlite3_int64);
+ /* Version 3.20.0 and later */
+ int (*prepare_v3)(sqlite3*,const char*,int,unsigned int,
+ sqlite3_stmt**,const char**);
+ int (*prepare16_v3)(sqlite3*,const void*,int,unsigned int,
+ sqlite3_stmt**,const void**);
+ int (*bind_pointer)(sqlite3_stmt*,int,void*,const char*,void(*)(void*));
+ void (*result_pointer)(sqlite3_context*,void*,const char*,void(*)(void*));
+ void *(*value_pointer)(sqlite3_value*,const char*);
+ int (*vtab_nochange)(sqlite3_context*);
+ int (*value_nochange)(sqlite3_value*);
+ const char *(*vtab_collation)(sqlite3_index_info*,int);
};
/*
@@ -110145,7 +113686,7 @@ typedef int (*sqlite3_loadext_entry)(
#define sqlite3_rollback_hook sqlite3_api->rollback_hook
#define sqlite3_set_authorizer sqlite3_api->set_authorizer
#define sqlite3_set_auxdata sqlite3_api->set_auxdata
-#define sqlite3_snprintf sqlite3_api->snprintf
+#define sqlite3_snprintf sqlite3_api->xsnprintf
#define sqlite3_step sqlite3_api->step
#define sqlite3_table_column_metadata sqlite3_api->table_column_metadata
#define sqlite3_thread_cleanup sqlite3_api->thread_cleanup
@@ -110169,7 +113710,7 @@ typedef int (*sqlite3_loadext_entry)(
#define sqlite3_value_text16le sqlite3_api->value_text16le
#define sqlite3_value_type sqlite3_api->value_type
#define sqlite3_vmprintf sqlite3_api->vmprintf
-#define sqlite3_vsnprintf sqlite3_api->vsnprintf
+#define sqlite3_vsnprintf sqlite3_api->xvsnprintf
#define sqlite3_overload_function sqlite3_api->overload_function
#define sqlite3_prepare_v2 sqlite3_api->prepare_v2
#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2
@@ -110245,7 +113786,7 @@ typedef int (*sqlite3_loadext_entry)(
#define sqlite3_uri_boolean sqlite3_api->uri_boolean
#define sqlite3_uri_int64 sqlite3_api->uri_int64
#define sqlite3_uri_parameter sqlite3_api->uri_parameter
-#define sqlite3_uri_vsnprintf sqlite3_api->vsnprintf
+#define sqlite3_uri_vsnprintf sqlite3_api->xvsnprintf
#define sqlite3_wal_checkpoint_v2 sqlite3_api->wal_checkpoint_v2
/* Version 3.8.7 and later */
#define sqlite3_auto_extension sqlite3_api->auto_extension
@@ -110277,6 +113818,18 @@ typedef int (*sqlite3_loadext_entry)(
/* Version 3.14.0 and later */
#define sqlite3_trace_v2 sqlite3_api->trace_v2
#define sqlite3_expanded_sql sqlite3_api->expanded_sql
+/* Version 3.18.0 and later */
+#define sqlite3_set_last_insert_rowid sqlite3_api->set_last_insert_rowid
+/* Version 3.20.0 and later */
+#define sqlite3_prepare_v3 sqlite3_api->prepare_v3
+#define sqlite3_prepare16_v3 sqlite3_api->prepare16_v3
+#define sqlite3_bind_pointer sqlite3_api->bind_pointer
+#define sqlite3_result_pointer sqlite3_api->result_pointer
+#define sqlite3_value_pointer sqlite3_api->value_pointer
+/* Version 3.22.0 and later */
+#define sqlite3_vtab_nochange sqlite3_api->vtab_nochange
+#define sqlite3_value_nochange sqltie3_api->value_nochange
+#define sqlite3_vtab_collation sqltie3_api->vtab_collation
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
@@ -110299,7 +113852,6 @@ typedef int (*sqlite3_loadext_entry)(
/************** End of sqlite3ext.h ******************************************/
/************** Continuing where we left off in loadext.c ********************/
/* #include "sqliteInt.h" */
-/* #include */
#ifndef SQLITE_OMIT_LOAD_EXTENSION
/*
@@ -110333,6 +113885,7 @@ typedef int (*sqlite3_loadext_entry)(
# define sqlite3_open16 0
# define sqlite3_prepare16 0
# define sqlite3_prepare16_v2 0
+# define sqlite3_prepare16_v3 0
# define sqlite3_result_error16 0
# define sqlite3_result_text16 0
# define sqlite3_result_text16be 0
@@ -110703,7 +114256,19 @@ static const sqlite3_api_routines sqlite3Apis = {
sqlite3_system_errno,
/* Version 3.14.0 and later */
sqlite3_trace_v2,
- sqlite3_expanded_sql
+ sqlite3_expanded_sql,
+ /* Version 3.18.0 and later */
+ sqlite3_set_last_insert_rowid,
+ /* Version 3.20.0 and later */
+ sqlite3_prepare_v3,
+ sqlite3_prepare16_v3,
+ sqlite3_bind_pointer,
+ sqlite3_result_pointer,
+ sqlite3_value_pointer,
+ /* Version 3.22.0 and later */
+ sqlite3_vtab_nochange,
+ sqlite3_value_nochange,
+ sqlite3_vtab_collation
};
/*
@@ -110769,8 +114334,10 @@ static int sqlite3LoadExtension(
#if SQLITE_OS_UNIX || SQLITE_OS_WIN
for(ii=0; iinPragCName;
+ sqlite3VdbeSetNumCols(v, n==0 ? 1 : n);
+ if( n==0 ){
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, pPragma->zName, SQLITE_STATIC);
+ }else{
+ int i, j;
+ for(i=0, j=pPragma->iPragCName; iupr ? 0 : &aPragmaName[mid];
+}
+
+/*
+** Helper subroutine for PRAGMA integrity_check:
+**
+** Generate code to output a single-column result row with a value of the
+** string held in register 3. Decrement the result count in register 1
+** and halt if the maximum number of result rows have been issued.
+*/
+static int integrityCheckResultRow(Vdbe *v){
+ int addr;
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1);
+ addr = sqlite3VdbeAddOp3(v, OP_IfPos, 1, sqlite3VdbeCurrentAddr(v)+2, 1);
+ VdbeCoverage(v);
+ sqlite3VdbeAddOp0(v, OP_Halt);
+ return addr;
+}
+
/*
** Process a pragma statement.
**
@@ -111846,12 +115632,11 @@ SQLITE_PRIVATE void sqlite3Pragma(
Token *pId; /* Pointer to token */
char *aFcntl[4]; /* Argument to SQLITE_FCNTL_PRAGMA */
int iDb; /* Database index for */
- int lwr, upr, mid = 0; /* Binary search bounds */
int rc; /* return value form SQLITE_FCNTL_PRAGMA */
sqlite3 *db = pParse->db; /* The database connection */
Db *pDb; /* The specific database being pragmaed */
Vdbe *v = sqlite3GetVdbe(pParse); /* Prepared statement */
- const struct sPragmaNames *pPragma;
+ const PragmaName *pPragma; /* The pragma */
if( v==0 ) return;
sqlite3VdbeRunOnlyOnce(v);
@@ -111906,7 +115691,9 @@ SQLITE_PRIVATE void sqlite3Pragma(
db->busyHandler.nBusy = 0;
rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_PRAGMA, (void*)aFcntl);
if( rc==SQLITE_OK ){
- returnSingleText(v, "result", aFcntl[0]);
+ sqlite3VdbeSetNumCols(v, 1);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, aFcntl[0], SQLITE_TRANSIENT);
+ returnSingleText(v, aFcntl[0]);
sqlite3_free(aFcntl[0]);
goto pragma_out;
}
@@ -111921,26 +115708,21 @@ SQLITE_PRIVATE void sqlite3Pragma(
}
/* Locate the pragma in the lookup table */
- lwr = 0;
- upr = ArraySize(aPragmaNames)-1;
- while( lwr<=upr ){
- mid = (lwr+upr)/2;
- rc = sqlite3_stricmp(zLeft, aPragmaNames[mid].zName);
- if( rc==0 ) break;
- if( rc<0 ){
- upr = mid - 1;
- }else{
- lwr = mid + 1;
- }
- }
- if( lwr>upr ) goto pragma_out;
- pPragma = &aPragmaNames[mid];
+ pPragma = pragmaLocate(zLeft);
+ if( pPragma==0 ) goto pragma_out;
/* Make sure the database schema is loaded if the pragma requires that */
- if( (pPragma->mPragFlag & PragFlag_NeedSchema)!=0 ){
+ if( (pPragma->mPragFlg & PragFlg_NeedSchema)!=0 ){
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
}
+ /* Register the result column names for pragmas that return results */
+ if( (pPragma->mPragFlg & PragFlg_NoColumns)==0
+ && ((pPragma->mPragFlg & PragFlg_NoColumns1)==0 || zRight==0)
+ ){
+ setPragmaResultColumnNames(v, pPragma);
+ }
+
/* Jump to the appropriate pragma handler */
switch( pPragma->ePragTyp ){
@@ -111977,7 +115759,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
VdbeOp *aOp;
sqlite3VdbeUsesBtree(v, iDb);
if( !zRight ){
- setOneColumnName(v, "cache_size");
pParse->nMem += 2;
sqlite3VdbeVerifyNoMallocRequired(v, ArraySize(getCacheSize));
aOp = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize, iLn);
@@ -112012,7 +115793,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
assert( pBt!=0 );
if( !zRight ){
int size = ALWAYS(pBt) ? sqlite3BtreeGetPageSize(pBt) : 0;
- returnSingleInt(v, "page_size", size);
+ returnSingleInt(v, size);
}else{
/* Malloc may fail when setting the page-size, as there is an internal
** buffer that the pager module resizes using sqlite3_realloc().
@@ -112027,18 +115808,22 @@ SQLITE_PRIVATE void sqlite3Pragma(
/*
** PRAGMA [schema.]secure_delete
- ** PRAGMA [schema.]secure_delete=ON/OFF
+ ** PRAGMA [schema.]secure_delete=ON/OFF/FAST
**
** The first form reports the current setting for the
** secure_delete flag. The second form changes the secure_delete
- ** flag setting and reports thenew value.
+ ** flag setting and reports the new value.
*/
case PragTyp_SECURE_DELETE: {
Btree *pBt = pDb->pBt;
int b = -1;
assert( pBt!=0 );
if( zRight ){
- b = sqlite3GetBoolean(zRight, 0);
+ if( sqlite3_stricmp(zRight, "fast")==0 ){
+ b = 2;
+ }else{
+ b = sqlite3GetBoolean(zRight, 0);
+ }
}
if( pId2->n==0 && b>=0 ){
int ii;
@@ -112047,7 +115832,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
}
}
b = sqlite3BtreeSecureDelete(pBt, b);
- returnSingleInt(v, "secure_delete", b);
+ returnSingleInt(v, b);
break;
}
@@ -112079,8 +115864,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3AbsInt32(sqlite3Atoi(zRight)));
}
sqlite3VdbeAddOp2(v, OP_ResultRow, iReg, 1);
- sqlite3VdbeSetNumCols(v, 1);
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, SQLITE_TRANSIENT);
break;
}
@@ -112126,7 +115909,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
if( eMode==PAGER_LOCKINGMODE_EXCLUSIVE ){
zRet = "exclusive";
}
- returnSingleText(v, "locking_mode", zRet);
+ returnSingleText(v, zRet);
break;
}
@@ -112139,7 +115922,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
int eMode; /* One of the PAGER_JOURNALMODE_XXX symbols */
int ii; /* Loop counter */
- setOneColumnName(v, "journal_mode");
if( zRight==0 ){
/* If there is no "=MODE" part of the pragma, do a query for the
** current mode */
@@ -112185,7 +115967,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
if( iLimit<-1 ) iLimit = -1;
}
iLimit = sqlite3PagerJournalSizeLimit(pPager, iLimit);
- returnSingleInt(v, "journal_size_limit", iLimit);
+ returnSingleInt(v, iLimit);
break;
}
@@ -112203,7 +115985,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
Btree *pBt = pDb->pBt;
assert( pBt!=0 );
if( !zRight ){
- returnSingleInt(v, "auto_vacuum", sqlite3BtreeGetAutoVacuum(pBt));
+ returnSingleInt(v, sqlite3BtreeGetAutoVacuum(pBt));
}else{
int eAuto = getAutoVacuum(zRight);
assert( eAuto>=0 && eAuto<=2 );
@@ -112282,7 +116064,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
case PragTyp_CACHE_SIZE: {
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
if( !zRight ){
- returnSingleInt(v, "cache_size", pDb->pSchema->cache_size);
+ returnSingleInt(v, pDb->pSchema->cache_size);
}else{
int size = sqlite3Atoi(zRight);
pDb->pSchema->cache_size = size;
@@ -112316,7 +116098,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
case PragTyp_CACHE_SPILL: {
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
if( !zRight ){
- returnSingleInt(v, "cache_spill",
+ returnSingleInt(v,
(db->flags & SQLITE_CacheSpill)==0 ? 0 :
sqlite3BtreeSetSpillSize(pDb->pBt,0));
}else{
@@ -112370,7 +116152,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
rc = SQLITE_OK;
#endif
if( rc==SQLITE_OK ){
- returnSingleInt(v, "mmap_size", sz);
+ returnSingleInt(v, sz);
}else if( rc!=SQLITE_NOTFOUND ){
pParse->nErr++;
pParse->rc = rc;
@@ -112391,7 +116173,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
*/
case PragTyp_TEMP_STORE: {
if( !zRight ){
- returnSingleInt(v, "temp_store", db->temp_store);
+ returnSingleInt(v, db->temp_store);
}else{
changeTempStorage(pParse, zRight);
}
@@ -112410,7 +116192,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
*/
case PragTyp_TEMP_STORE_DIRECTORY: {
if( !zRight ){
- returnSingleText(v, "temp_store_directory", sqlite3_temp_directory);
+ returnSingleText(v, sqlite3_temp_directory);
}else{
#ifndef SQLITE_OMIT_WSD
if( zRight[0] ){
@@ -112454,7 +116236,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
*/
case PragTyp_DATA_STORE_DIRECTORY: {
if( !zRight ){
- returnSingleText(v, "data_store_directory", sqlite3_data_directory);
+ returnSingleText(v, sqlite3_data_directory);
}else{
#ifndef SQLITE_OMIT_WSD
if( zRight[0] ){
@@ -112493,7 +116275,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3_file *pFile = sqlite3PagerFile(pPager);
sqlite3OsFileControlHint(pFile, SQLITE_GET_LOCKPROXYFILE,
&proxy_file_path);
- returnSingleText(v, "lock_proxy_file", proxy_file_path);
+ returnSingleText(v, proxy_file_path);
}else{
Pager *pPager = sqlite3BtreePager(pDb->pBt);
sqlite3_file *pFile = sqlite3PagerFile(pPager);
@@ -112525,12 +116307,12 @@ SQLITE_PRIVATE void sqlite3Pragma(
*/
case PragTyp_SYNCHRONOUS: {
if( !zRight ){
- returnSingleInt(v, "synchronous", pDb->safety_level-1);
+ returnSingleInt(v, pDb->safety_level-1);
}else{
if( !db->autoCommit ){
sqlite3ErrorMsg(pParse,
"Safety level may not be changed inside a transaction");
- }else{
+ }else if( iDb!=1 ){
int iLevel = (getSafetyLevel(zRight,0,1)+1) & PAGER_SYNCHRONOUS_MASK;
if( iLevel==0 ) iLevel = 1;
pDb->safety_level = iLevel;
@@ -112545,7 +116327,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
#ifndef SQLITE_OMIT_FLAG_PRAGMAS
case PragTyp_FLAG: {
if( zRight==0 ){
- returnSingleInt(v, pPragma->zName, (db->flags & pPragma->iArg)!=0 );
+ setPragmaResultColumnNames(v, pPragma);
+ returnSingleInt(v, (db->flags & pPragma->iArg)!=0 );
}else{
int mask = pPragma->iArg; /* Mask of bits to set or clear. */
if( db->autoCommit==0 ){
@@ -112590,21 +116373,18 @@ SQLITE_PRIVATE void sqlite3Pragma(
** type: Column declaration type.
** notnull: True if 'NOT NULL' is part of column declaration
** dflt_value: The default value for the column, if any.
+ ** pk: Non-zero for PK fields.
*/
case PragTyp_TABLE_INFO: if( zRight ){
Table *pTab;
pTab = sqlite3LocateTable(pParse, LOCATE_NOERR, zRight, zDb);
if( pTab ){
- static const char *azCol[] = {
- "cid", "name", "type", "notnull", "dflt_value", "pk"
- };
int i, k;
int nHidden = 0;
Column *pCol;
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
pParse->nMem = 6;
sqlite3CodeVerifySchema(pParse, iDb);
- setAllColumnNames(v, 6, azCol); assert( 6==ArraySize(azCol) );
sqlite3ViewGetColumnNames(pParse, pTab);
for(i=0, pCol=pTab->aCol; inCol; i++, pCol++){
if( IsHiddenColumn(pCol) ){
@@ -112626,47 +116406,43 @@ SQLITE_PRIVATE void sqlite3Pragma(
pCol->notNull ? 1 : 0,
pCol->pDflt ? pCol->pDflt->u.zToken : 0,
k);
- sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6);
}
}
}
break;
+#ifdef SQLITE_DEBUG
case PragTyp_STATS: {
- static const char *azCol[] = { "table", "index", "width", "height" };
Index *pIdx;
HashElem *i;
- v = sqlite3GetVdbe(pParse);
- pParse->nMem = 4;
+ pParse->nMem = 5;
sqlite3CodeVerifySchema(pParse, iDb);
- setAllColumnNames(v, 4, azCol); assert( 4==ArraySize(azCol) );
for(i=sqliteHashFirst(&pDb->pSchema->tblHash); i; i=sqliteHashNext(i)){
Table *pTab = sqliteHashData(i);
- sqlite3VdbeMultiLoad(v, 1, "ssii",
+ sqlite3VdbeMultiLoad(v, 1, "ssiii",
pTab->zName,
0,
pTab->szTabRow,
- pTab->nRowLogEst);
- sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4);
+ pTab->nRowLogEst,
+ pTab->tabFlags);
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- sqlite3VdbeMultiLoad(v, 2, "sii",
+ sqlite3VdbeMultiLoad(v, 2, "siiiX",
pIdx->zName,
pIdx->szIdxRow,
- pIdx->aiRowLogEst[0]);
- sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4);
+ pIdx->aiRowLogEst[0],
+ pIdx->hasStat1);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 5);
}
}
}
break;
+#endif
case PragTyp_INDEX_INFO: if( zRight ){
Index *pIdx;
Table *pTab;
pIdx = sqlite3FindIndex(db, zRight, zDb);
if( pIdx ){
- static const char *azCol[] = {
- "seqno", "cid", "name", "desc", "coll", "key"
- };
int i;
int mx;
if( pPragma->iArg ){
@@ -112680,14 +116456,13 @@ SQLITE_PRIVATE void sqlite3Pragma(
}
pTab = pIdx->pTable;
sqlite3CodeVerifySchema(pParse, iDb);
- assert( pParse->nMem<=ArraySize(azCol) );
- setAllColumnNames(v, pParse->nMem, azCol);
+ assert( pParse->nMem<=pPragma->nPragCName );
for(i=0; iaiColumn[i];
- sqlite3VdbeMultiLoad(v, 1, "iis", i, cnum,
+ sqlite3VdbeMultiLoad(v, 1, "iisX", i, cnum,
cnum<0 ? 0 : pTab->aCol[cnum].zName);
if( pPragma->iArg ){
- sqlite3VdbeMultiLoad(v, 4, "isi",
+ sqlite3VdbeMultiLoad(v, 4, "isiX",
pIdx->aSortOrder[i],
pIdx->azColl[i],
inKeyCol);
@@ -112704,13 +116479,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
int i;
pTab = sqlite3FindTable(db, zRight, zDb);
if( pTab ){
- static const char *azCol[] = {
- "seq", "name", "unique", "origin", "partial"
- };
- v = sqlite3GetVdbe(pParse);
pParse->nMem = 5;
sqlite3CodeVerifySchema(pParse, iDb);
- setAllColumnNames(v, 5, azCol); assert( 5==ArraySize(azCol) );
for(pIdx=pTab->pIndex, i=0; pIdx; pIdx=pIdx->pNext, i++){
const char *azOrigin[] = { "c", "u", "pk" };
sqlite3VdbeMultiLoad(v, 1, "isisi",
@@ -112719,17 +116489,14 @@ SQLITE_PRIVATE void sqlite3Pragma(
IsUniqueIndex(pIdx),
azOrigin[pIdx->idxType],
pIdx->pPartIdxWhere!=0);
- sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 5);
}
}
}
break;
case PragTyp_DATABASE_LIST: {
- static const char *azCol[] = { "seq", "name", "file" };
int i;
pParse->nMem = 3;
- setAllColumnNames(v, 3, azCol); assert( 3==ArraySize(azCol) );
for(i=0; inDb; i++){
if( db->aDb[i].pBt==0 ) continue;
assert( db->aDb[i].zDbSName!=0 );
@@ -112737,24 +116504,60 @@ SQLITE_PRIVATE void sqlite3Pragma(
i,
db->aDb[i].zDbSName,
sqlite3BtreeGetFilename(db->aDb[i].pBt));
- sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
}
}
break;
case PragTyp_COLLATION_LIST: {
- static const char *azCol[] = { "seq", "name" };
int i = 0;
HashElem *p;
pParse->nMem = 2;
- setAllColumnNames(v, 2, azCol); assert( 2==ArraySize(azCol) );
for(p=sqliteHashFirst(&db->aCollSeq); p; p=sqliteHashNext(p)){
CollSeq *pColl = (CollSeq *)sqliteHashData(p);
sqlite3VdbeMultiLoad(v, 1, "is", i++, pColl->zName);
- sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2);
}
}
break;
+
+#ifdef SQLITE_INTROSPECTION_PRAGMAS
+ case PragTyp_FUNCTION_LIST: {
+ int i;
+ HashElem *j;
+ FuncDef *p;
+ pParse->nMem = 2;
+ for(i=0; iu.pHash ){
+ sqlite3VdbeMultiLoad(v, 1, "si", p->zName, 1);
+ }
+ }
+ for(j=sqliteHashFirst(&db->aFunc); j; j=sqliteHashNext(j)){
+ p = (FuncDef*)sqliteHashData(j);
+ sqlite3VdbeMultiLoad(v, 1, "si", p->zName, 0);
+ }
+ }
+ break;
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ case PragTyp_MODULE_LIST: {
+ HashElem *j;
+ pParse->nMem = 1;
+ for(j=sqliteHashFirst(&db->aModule); j; j=sqliteHashNext(j)){
+ Module *pMod = (Module*)sqliteHashData(j);
+ sqlite3VdbeMultiLoad(v, 1, "s", pMod->zName);
+ }
+ }
+ break;
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+ case PragTyp_PRAGMA_LIST: {
+ int i;
+ for(i=0; ipFKey;
if( pFK ){
- static const char *azCol[] = {
- "id", "seq", "table", "from", "to", "on_update", "on_delete",
- "match"
- };
int i = 0;
pParse->nMem = 8;
sqlite3CodeVerifySchema(pParse, iDb);
- setAllColumnNames(v, 8, azCol); assert( 8==ArraySize(azCol) );
while(pFK){
int j;
for(j=0; jnCol; j++){
@@ -112786,7 +116583,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
actionName(pFK->aAction[1]), /* ON UPDATE */
actionName(pFK->aAction[0]), /* ON DELETE */
"NONE");
- sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 8);
}
++i;
pFK = pFK->pNextFrom;
@@ -112814,14 +116610,11 @@ SQLITE_PRIVATE void sqlite3Pragma(
int addrTop; /* Top of a loop checking foreign keys */
int addrOk; /* Jump here if the key is OK */
int *aiCols; /* child to parent column mapping */
- static const char *azCol[] = { "table", "rowid", "parent", "fkid" };
regResult = pParse->nMem+1;
pParse->nMem += 4;
regKey = ++pParse->nMem;
regRow = ++pParse->nMem;
- v = sqlite3GetVdbe(pParse);
- setAllColumnNames(v, 4, azCol); assert( 4==ArraySize(azCol) );
sqlite3CodeVerifySchema(pParse, iDb);
k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash);
while( k ){
@@ -112868,34 +116661,38 @@ SQLITE_PRIVATE void sqlite3Pragma(
assert( x==0 );
}
addrOk = sqlite3VdbeMakeLabel(v);
- if( pParent && pIdx==0 ){
- int iKey = pFK->aCol[0].iFrom;
- assert( iKey>=0 && iKeynCol );
- if( iKey!=pTab->iPKey ){
- sqlite3VdbeAddOp3(v, OP_Column, 0, iKey, regRow);
- sqlite3ColumnDefault(v, pTab, iKey, regRow);
- sqlite3VdbeAddOp2(v, OP_IsNull, regRow, addrOk); VdbeCoverage(v);
- }else{
- sqlite3VdbeAddOp2(v, OP_Rowid, 0, regRow);
- }
- sqlite3VdbeAddOp3(v, OP_SeekRowid, i, 0, regRow); VdbeCoverage(v);
+
+ /* Generate code to read the child key values into registers
+ ** regRow..regRow+n. If any of the child key values are NULL, this
+ ** row cannot cause an FK violation. Jump directly to addrOk in
+ ** this case. */
+ for(j=0; jnCol; j++){
+ int iCol = aiCols ? aiCols[j] : pFK->aCol[j].iFrom;
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, 0, iCol, regRow+j);
+ sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk); VdbeCoverage(v);
+ }
+
+ /* Generate code to query the parent index for a matching parent
+ ** key. If a match is found, jump to addrOk. */
+ if( pIdx ){
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, pFK->nCol, regKey,
+ sqlite3IndexAffinityStr(db,pIdx), pFK->nCol);
+ sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0);
+ VdbeCoverage(v);
+ }else if( pParent ){
+ int jmp = sqlite3VdbeCurrentAddr(v)+2;
+ sqlite3VdbeAddOp3(v, OP_SeekRowid, i, jmp, regRow); VdbeCoverage(v);
sqlite3VdbeGoto(v, addrOk);
- sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2);
+ assert( pFK->nCol==1 );
+ }
+
+ /* Generate code to report an FK violation to the caller. */
+ if( HasRowid(pTab) ){
+ sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1);
}else{
- for(j=0; jnCol; j++){
- sqlite3ExprCodeGetColumnOfTable(v, pTab, 0,
- aiCols ? aiCols[j] : pFK->aCol[j].iFrom, regRow+j);
- sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk); VdbeCoverage(v);
- }
- if( pParent ){
- sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, pFK->nCol, regKey,
- sqlite3IndexAffinityStr(db,pIdx), pFK->nCol);
- sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0);
- VdbeCoverage(v);
- }
+ sqlite3VdbeAddOp2(v, OP_Null, 0, regResult+1);
}
- sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1);
- sqlite3VdbeMultiLoad(v, regResult+2, "si", pFK->zTo, i-1);
+ sqlite3VdbeMultiLoad(v, regResult+2, "siX", pFK->zTo, i-1);
sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 4);
sqlite3VdbeResolveLabel(v, addrOk);
sqlite3DbFree(db, aiCols);
@@ -112936,9 +116733,17 @@ SQLITE_PRIVATE void sqlite3Pragma(
#endif
#ifndef SQLITE_OMIT_INTEGRITY_CHECK
- /* Pragma "quick_check" is reduced version of
+ /* PRAGMA integrity_check
+ ** PRAGMA integrity_check(N)
+ ** PRAGMA quick_check
+ ** PRAGMA quick_check(N)
+ **
+ ** Verify the integrity of the database.
+ **
+ ** The "quick_check" is reduced version of
** integrity_check designed to detect most database corruption
- ** without most of the overhead of a full integrity-check.
+ ** without the overhead of cross-checking indexes. Quick_check
+ ** is linear time wherease integrity_check is O(NlogN).
*/
case PragTyp_INTEGRITY_CHECK: {
int i, j, addr, mxErr;
@@ -112960,7 +116765,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
/* Initialize the VDBE program */
pParse->nMem = 6;
- setOneColumnName(v, "integrity_check");
/* Set the maximum error count */
mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX;
@@ -112970,25 +116774,20 @@ SQLITE_PRIVATE void sqlite3Pragma(
mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX;
}
}
- sqlite3VdbeAddOp2(v, OP_Integer, mxErr, 1); /* reg[1] holds errors left */
+ sqlite3VdbeAddOp2(v, OP_Integer, mxErr-1, 1); /* reg[1] holds errors left */
/* Do an integrity check on each database file */
for(i=0; inDb; i++){
- HashElem *x;
- Hash *pTbls;
- int *aRoot;
- int cnt = 0;
- int mxIdx = 0;
- int nIdx;
+ HashElem *x; /* For looping over tables in the schema */
+ Hash *pTbls; /* Set of all tables in the schema */
+ int *aRoot; /* Array of root page numbers of all btrees */
+ int cnt = 0; /* Number of entries in aRoot[] */
+ int mxIdx = 0; /* Maximum number of indexes for any table */
if( OMIT_TEMPDB && i==1 ) continue;
if( iDb>=0 && i!=iDb ) continue;
sqlite3CodeVerifySchema(pParse, i);
- addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Halt if out of errors */
- VdbeCoverage(v);
- sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
- sqlite3VdbeJumpHere(v, addr);
/* Do an integrity check of the B-Tree
**
@@ -112998,8 +116797,9 @@ SQLITE_PRIVATE void sqlite3Pragma(
assert( sqlite3SchemaMutexHeld(db, i, 0) );
pTbls = &db->aDb[i].pSchema->tblHash;
for(cnt=0, x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
- Table *pTab = sqliteHashData(x);
- Index *pIdx;
+ Table *pTab = sqliteHashData(x); /* Current table */
+ Index *pIdx; /* An index on pTab */
+ int nIdx; /* Number of indexes on pTab */
if( HasRowid(pTab) ) cnt++;
for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){ cnt++; }
if( nIdx>mxIdx ) mxIdx = nIdx;
@@ -113009,15 +116809,16 @@ SQLITE_PRIVATE void sqlite3Pragma(
for(cnt=0, x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
Table *pTab = sqliteHashData(x);
Index *pIdx;
- if( HasRowid(pTab) ) aRoot[cnt++] = pTab->tnum;
+ if( HasRowid(pTab) ) aRoot[++cnt] = pTab->tnum;
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- aRoot[cnt++] = pIdx->tnum;
+ aRoot[++cnt] = pIdx->tnum;
}
}
- aRoot[cnt] = 0;
+ aRoot[0] = cnt;
/* Make sure sufficient number of registers have been allocated */
pParse->nMem = MAX( pParse->nMem, 8+mxIdx );
+ sqlite3ClearTempRegCache(pParse);
/* Do the b-tree integrity checks */
sqlite3VdbeAddOp4(v, OP_IntegrityCk, 2, cnt, 1, (char*)aRoot,P4_INTARRAY);
@@ -113026,14 +116827,13 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zDbSName),
P4_DYNAMIC);
- sqlite3VdbeAddOp3(v, OP_Move, 2, 4, 1);
- sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 2);
- sqlite3VdbeAddOp2(v, OP_ResultRow, 2, 1);
+ sqlite3VdbeAddOp3(v, OP_Concat, 2, 3, 3);
+ integrityCheckResultRow(v);
sqlite3VdbeJumpHere(v, addr);
/* Make sure all the indices are constructed correctly.
*/
- for(x=sqliteHashFirst(pTbls); x && !isQuick; x=sqliteHashNext(x)){
+ for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
Table *pTab = sqliteHashData(x);
Index *pIdx, *pPk;
Index *pPrior = 0;
@@ -113041,15 +116841,14 @@ SQLITE_PRIVATE void sqlite3Pragma(
int iDataCur, iIdxCur;
int r1 = -1;
- if( pTab->pIndex==0 ) continue;
+ if( pTab->tnum<1 ) continue; /* Skip VIEWs or VIRTUAL TABLEs */
pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
- addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Stop if out of errors */
- VdbeCoverage(v);
- sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
- sqlite3VdbeJumpHere(v, addr);
sqlite3ExprCacheClear(pParse);
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0,
1, 0, &iDataCur, &iIdxCur);
+ /* reg[7] counts the number of entries in the table.
+ ** reg[8+i] counts the number of entries in the i-th index
+ */
sqlite3VdbeAddOp2(v, OP_Integer, 0, 7);
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
sqlite3VdbeAddOp2(v, OP_Integer, 0, 8+j); /* index entries counter */
@@ -113061,88 +116860,110 @@ SQLITE_PRIVATE void sqlite3Pragma(
/* Verify that all NOT NULL columns really are NOT NULL */
for(j=0; jnCol; j++){
char *zErr;
- int jmp2, jmp3;
+ int jmp2;
if( j==pTab->iPKey ) continue;
if( pTab->aCol[j].notNull==0 ) continue;
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3);
sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
jmp2 = sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v);
- sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */
zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName,
pTab->aCol[j].zName);
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
- sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1);
- jmp3 = sqlite3VdbeAddOp1(v, OP_IfPos, 1); VdbeCoverage(v);
- sqlite3VdbeAddOp0(v, OP_Halt);
+ integrityCheckResultRow(v);
sqlite3VdbeJumpHere(v, jmp2);
- sqlite3VdbeJumpHere(v, jmp3);
}
- /* Validate index entries for the current row */
- for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
- int jmp2, jmp3, jmp4, jmp5;
- int ckUniq = sqlite3VdbeMakeLabel(v);
- if( pPk==pIdx ) continue;
- r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3,
- pPrior, r1);
- pPrior = pIdx;
- sqlite3VdbeAddOp2(v, OP_AddImm, 8+j, 1); /* increment entry count */
- /* Verify that an index entry exists for the current table row */
- jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, ckUniq, r1,
- pIdx->nColumn); VdbeCoverage(v);
- sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */
- sqlite3VdbeLoadString(v, 3, "row ");
- sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3);
- sqlite3VdbeLoadString(v, 4, " missing from index ");
- sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
- jmp5 = sqlite3VdbeLoadString(v, 4, pIdx->zName);
- sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
- sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1);
- jmp4 = sqlite3VdbeAddOp1(v, OP_IfPos, 1); VdbeCoverage(v);
- sqlite3VdbeAddOp0(v, OP_Halt);
- sqlite3VdbeJumpHere(v, jmp2);
- /* For UNIQUE indexes, verify that only one entry exists with the
- ** current key. The entry is unique if (1) any column is NULL
- ** or (2) the next entry has a different key */
- if( IsUniqueIndex(pIdx) ){
- int uniqOk = sqlite3VdbeMakeLabel(v);
- int jmp6;
- int kk;
- for(kk=0; kknKeyCol; kk++){
- int iCol = pIdx->aiColumn[kk];
- assert( iCol!=XN_ROWID && iColnCol );
- if( iCol>=0 && pTab->aCol[iCol].notNull ) continue;
- sqlite3VdbeAddOp2(v, OP_IsNull, r1+kk, uniqOk);
- VdbeCoverage(v);
+ /* Verify CHECK constraints */
+ if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){
+ ExprList *pCheck = sqlite3ExprListDup(db, pTab->pCheck, 0);
+ if( db->mallocFailed==0 ){
+ int addrCkFault = sqlite3VdbeMakeLabel(v);
+ int addrCkOk = sqlite3VdbeMakeLabel(v);
+ char *zErr;
+ int k;
+ pParse->iSelfTab = iDataCur + 1;
+ sqlite3ExprCachePush(pParse);
+ for(k=pCheck->nExpr-1; k>0; k--){
+ sqlite3ExprIfFalse(pParse, pCheck->a[k].pExpr, addrCkFault, 0);
}
- jmp6 = sqlite3VdbeAddOp1(v, OP_Next, iIdxCur+j); VdbeCoverage(v);
- sqlite3VdbeGoto(v, uniqOk);
- sqlite3VdbeJumpHere(v, jmp6);
- sqlite3VdbeAddOp4Int(v, OP_IdxGT, iIdxCur+j, uniqOk, r1,
- pIdx->nKeyCol); VdbeCoverage(v);
- sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */
- sqlite3VdbeLoadString(v, 3, "non-unique entry in index ");
- sqlite3VdbeGoto(v, jmp5);
- sqlite3VdbeResolveLabel(v, uniqOk);
+ sqlite3ExprIfTrue(pParse, pCheck->a[0].pExpr, addrCkOk,
+ SQLITE_JUMPIFNULL);
+ sqlite3VdbeResolveLabel(v, addrCkFault);
+ pParse->iSelfTab = 0;
+ zErr = sqlite3MPrintf(db, "CHECK constraint failed in %s",
+ pTab->zName);
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
+ integrityCheckResultRow(v);
+ sqlite3VdbeResolveLabel(v, addrCkOk);
+ sqlite3ExprCachePop(pParse);
+ }
+ sqlite3ExprListDelete(db, pCheck);
+ }
+ if( !isQuick ){ /* Omit the remaining tests for quick_check */
+ /* Sanity check on record header decoding */
+ sqlite3VdbeAddOp3(v, OP_Column, iDataCur, pTab->nCol-1, 3);
+ sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
+ /* Validate index entries for the current row */
+ for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
+ int jmp2, jmp3, jmp4, jmp5;
+ int ckUniq = sqlite3VdbeMakeLabel(v);
+ if( pPk==pIdx ) continue;
+ r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3,
+ pPrior, r1);
+ pPrior = pIdx;
+ sqlite3VdbeAddOp2(v, OP_AddImm, 8+j, 1);/* increment entry count */
+ /* Verify that an index entry exists for the current table row */
+ jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, ckUniq, r1,
+ pIdx->nColumn); VdbeCoverage(v);
+ sqlite3VdbeLoadString(v, 3, "row ");
+ sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3);
+ sqlite3VdbeLoadString(v, 4, " missing from index ");
+ sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
+ jmp5 = sqlite3VdbeLoadString(v, 4, pIdx->zName);
+ sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
+ jmp4 = integrityCheckResultRow(v);
+ sqlite3VdbeJumpHere(v, jmp2);
+ /* For UNIQUE indexes, verify that only one entry exists with the
+ ** current key. The entry is unique if (1) any column is NULL
+ ** or (2) the next entry has a different key */
+ if( IsUniqueIndex(pIdx) ){
+ int uniqOk = sqlite3VdbeMakeLabel(v);
+ int jmp6;
+ int kk;
+ for(kk=0; kknKeyCol; kk++){
+ int iCol = pIdx->aiColumn[kk];
+ assert( iCol!=XN_ROWID && iColnCol );
+ if( iCol>=0 && pTab->aCol[iCol].notNull ) continue;
+ sqlite3VdbeAddOp2(v, OP_IsNull, r1+kk, uniqOk);
+ VdbeCoverage(v);
+ }
+ jmp6 = sqlite3VdbeAddOp1(v, OP_Next, iIdxCur+j); VdbeCoverage(v);
+ sqlite3VdbeGoto(v, uniqOk);
+ sqlite3VdbeJumpHere(v, jmp6);
+ sqlite3VdbeAddOp4Int(v, OP_IdxGT, iIdxCur+j, uniqOk, r1,
+ pIdx->nKeyCol); VdbeCoverage(v);
+ sqlite3VdbeLoadString(v, 3, "non-unique entry in index ");
+ sqlite3VdbeGoto(v, jmp5);
+ sqlite3VdbeResolveLabel(v, uniqOk);
+ }
+ sqlite3VdbeJumpHere(v, jmp4);
+ sqlite3ResolvePartIdxLabel(pParse, jmp3);
}
- sqlite3VdbeJumpHere(v, jmp4);
- sqlite3ResolvePartIdxLabel(pParse, jmp3);
}
sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, loopTop-1);
#ifndef SQLITE_OMIT_BTREECOUNT
- sqlite3VdbeLoadString(v, 2, "wrong # of entries in index ");
- for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
- if( pPk==pIdx ) continue;
- addr = sqlite3VdbeCurrentAddr(v);
- sqlite3VdbeAddOp2(v, OP_IfPos, 1, addr+2); VdbeCoverage(v);
- sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
- sqlite3VdbeAddOp2(v, OP_Count, iIdxCur+j, 3);
- sqlite3VdbeAddOp3(v, OP_Eq, 8+j, addr+8, 3); VdbeCoverage(v);
- sqlite3VdbeChangeP5(v, SQLITE_NOTNULL);
- sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1);
- sqlite3VdbeLoadString(v, 3, pIdx->zName);
- sqlite3VdbeAddOp3(v, OP_Concat, 3, 2, 7);
- sqlite3VdbeAddOp2(v, OP_ResultRow, 7, 1);
+ if( !isQuick ){
+ sqlite3VdbeLoadString(v, 2, "wrong # of entries in index ");
+ for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
+ if( pPk==pIdx ) continue;
+ sqlite3VdbeAddOp2(v, OP_Count, iIdxCur+j, 3);
+ addr = sqlite3VdbeAddOp3(v, OP_Eq, 8+j, 0, 3); VdbeCoverage(v);
+ sqlite3VdbeChangeP5(v, SQLITE_NOTNULL);
+ sqlite3VdbeLoadString(v, 4, pIdx->zName);
+ sqlite3VdbeAddOp3(v, OP_Concat, 4, 2, 3);
+ integrityCheckResultRow(v);
+ sqlite3VdbeJumpHere(v, addr);
+ }
}
#endif /* SQLITE_OMIT_BTREECOUNT */
}
@@ -113151,18 +116972,24 @@ SQLITE_PRIVATE void sqlite3Pragma(
static const int iLn = VDBE_OFFSET_LINENO(2);
static const VdbeOpList endCode[] = {
{ OP_AddImm, 1, 0, 0}, /* 0 */
- { OP_If, 1, 4, 0}, /* 1 */
+ { OP_IfNotZero, 1, 4, 0}, /* 1 */
{ OP_String8, 0, 3, 0}, /* 2 */
{ OP_ResultRow, 3, 1, 0}, /* 3 */
+ { OP_Halt, 0, 0, 0}, /* 4 */
+ { OP_String8, 0, 3, 0}, /* 5 */
+ { OP_Goto, 0, 3, 0}, /* 6 */
};
VdbeOp *aOp;
aOp = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode, iLn);
if( aOp ){
- aOp[0].p2 = -mxErr;
+ aOp[0].p2 = 1-mxErr;
aOp[2].p4type = P4_STATIC;
aOp[2].p4.z = "ok";
+ aOp[5].p4type = P4_STATIC;
+ aOp[5].p4.z = (char*)sqlite3ErrStr(SQLITE_CORRUPT);
}
+ sqlite3VdbeChangeP3(v, 0, sqlite3VdbeCurrentAddr(v)-2);
}
}
break;
@@ -113212,7 +117039,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
assert( encnames[SQLITE_UTF8].enc==SQLITE_UTF8 );
assert( encnames[SQLITE_UTF16LE].enc==SQLITE_UTF16LE );
assert( encnames[SQLITE_UTF16BE].enc==SQLITE_UTF16BE );
- returnSingleText(v, "encoding", encnames[ENC(pParse->db)].zName);
+ returnSingleText(v, encnames[ENC(pParse->db)].zName);
}else{ /* "PRAGMA encoding = XXX" */
/* Only change the value of sqlite.enc if the database handle is not
** initialized. If the main database exists, the new sqlite.enc value
@@ -113275,7 +117102,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
case PragTyp_HEADER_VALUE: {
int iCookie = pPragma->iArg; /* Which cookie to read or write */
sqlite3VdbeUsesBtree(v, iDb);
- if( zRight && (pPragma->mPragFlag & PragFlag_ReadOnly)==0 ){
+ if( zRight && (pPragma->mPragFlg & PragFlg_ReadOnly)==0 ){
/* Write the specified cookie value */
static const VdbeOpList setCookie[] = {
{ OP_Transaction, 0, 1, 0}, /* 0 */
@@ -113303,8 +117130,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
aOp[0].p1 = iDb;
aOp[1].p1 = iDb;
aOp[1].p3 = iCookie;
- sqlite3VdbeSetNumCols(v, 1);
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, SQLITE_TRANSIENT);
sqlite3VdbeReusable(v);
}
}
@@ -113322,7 +117147,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
int i = 0;
const char *zOpt;
pParse->nMem = 1;
- setOneColumnName(v, "compile_option");
while( (zOpt = sqlite3_compileoption_get(i++))!=0 ){
sqlite3VdbeLoadString(v, 1, zOpt);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
@@ -113339,7 +117163,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
** Checkpoint the database.
*/
case PragTyp_WAL_CHECKPOINT: {
- static const char *azCol[] = { "busy", "log", "checkpointed" };
int iBt = (pId2->z?iDb:SQLITE_MAX_ATTACHED);
int eMode = SQLITE_CHECKPOINT_PASSIVE;
if( zRight ){
@@ -113351,7 +117174,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
eMode = SQLITE_CHECKPOINT_TRUNCATE;
}
}
- setAllColumnNames(v, 3, azCol); assert( 3==ArraySize(azCol) );
pParse->nMem = 3;
sqlite3VdbeAddOp3(v, OP_Checkpoint, iBt, eMode, 1);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
@@ -113370,7 +117192,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
if( zRight ){
sqlite3_wal_autocheckpoint(db, sqlite3Atoi(zRight));
}
- returnSingleInt(v, "wal_autocheckpoint",
+ returnSingleInt(v,
db->xWalCallback==sqlite3WalDefaultHook ?
SQLITE_PTR_TO_INT(db->pWalArg) : 0);
}
@@ -113389,6 +117211,119 @@ SQLITE_PRIVATE void sqlite3Pragma(
break;
}
+ /*
+ ** PRAGMA optimize
+ ** PRAGMA optimize(MASK)
+ ** PRAGMA schema.optimize
+ ** PRAGMA schema.optimize(MASK)
+ **
+ ** Attempt to optimize the database. All schemas are optimized in the first
+ ** two forms, and only the specified schema is optimized in the latter two.
+ **
+ ** The details of optimizations performed by this pragma are expected
+ ** to change and improve over time. Applications should anticipate that
+ ** this pragma will perform new optimizations in future releases.
+ **
+ ** The optional argument is a bitmask of optimizations to perform:
+ **
+ ** 0x0001 Debugging mode. Do not actually perform any optimizations
+ ** but instead return one line of text for each optimization
+ ** that would have been done. Off by default.
+ **
+ ** 0x0002 Run ANALYZE on tables that might benefit. On by default.
+ ** See below for additional information.
+ **
+ ** 0x0004 (Not yet implemented) Record usage and performance
+ ** information from the current session in the
+ ** database file so that it will be available to "optimize"
+ ** pragmas run by future database connections.
+ **
+ ** 0x0008 (Not yet implemented) Create indexes that might have
+ ** been helpful to recent queries
+ **
+ ** The default MASK is and always shall be 0xfffe. 0xfffe means perform all
+ ** of the optimizations listed above except Debug Mode, including new
+ ** optimizations that have not yet been invented. If new optimizations are
+ ** ever added that should be off by default, those off-by-default
+ ** optimizations will have bitmasks of 0x10000 or larger.
+ **
+ ** DETERMINATION OF WHEN TO RUN ANALYZE
+ **
+ ** In the current implementation, a table is analyzed if only if all of
+ ** the following are true:
+ **
+ ** (1) MASK bit 0x02 is set.
+ **
+ ** (2) The query planner used sqlite_stat1-style statistics for one or
+ ** more indexes of the table at some point during the lifetime of
+ ** the current connection.
+ **
+ ** (3) One or more indexes of the table are currently unanalyzed OR
+ ** the number of rows in the table has increased by 25 times or more
+ ** since the last time ANALYZE was run.
+ **
+ ** The rules for when tables are analyzed are likely to change in
+ ** future releases.
+ */
+ case PragTyp_OPTIMIZE: {
+ int iDbLast; /* Loop termination point for the schema loop */
+ int iTabCur; /* Cursor for a table whose size needs checking */
+ HashElem *k; /* Loop over tables of a schema */
+ Schema *pSchema; /* The current schema */
+ Table *pTab; /* A table in the schema */
+ Index *pIdx; /* An index of the table */
+ LogEst szThreshold; /* Size threshold above which reanalysis is needd */
+ char *zSubSql; /* SQL statement for the OP_SqlExec opcode */
+ u32 opMask; /* Mask of operations to perform */
+
+ if( zRight ){
+ opMask = (u32)sqlite3Atoi(zRight);
+ if( (opMask & 0x02)==0 ) break;
+ }else{
+ opMask = 0xfffe;
+ }
+ iTabCur = pParse->nTab++;
+ for(iDbLast = zDb?iDb:db->nDb-1; iDb<=iDbLast; iDb++){
+ if( iDb==1 ) continue;
+ sqlite3CodeVerifySchema(pParse, iDb);
+ pSchema = db->aDb[iDb].pSchema;
+ for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){
+ pTab = (Table*)sqliteHashData(k);
+
+ /* If table pTab has not been used in a way that would benefit from
+ ** having analysis statistics during the current session, then skip it.
+ ** This also has the effect of skipping virtual tables and views */
+ if( (pTab->tabFlags & TF_StatsUsed)==0 ) continue;
+
+ /* Reanalyze if the table is 25 times larger than the last analysis */
+ szThreshold = pTab->nRowLogEst + 46; assert( sqlite3LogEst(25)==46 );
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ if( !pIdx->hasStat1 ){
+ szThreshold = 0; /* Always analyze if any index lacks statistics */
+ break;
+ }
+ }
+ if( szThreshold ){
+ sqlite3OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenRead);
+ sqlite3VdbeAddOp3(v, OP_IfSmaller, iTabCur,
+ sqlite3VdbeCurrentAddr(v)+2+(opMask&1), szThreshold);
+ VdbeCoverage(v);
+ }
+ zSubSql = sqlite3MPrintf(db, "ANALYZE \"%w\".\"%w\"",
+ db->aDb[iDb].zDbSName, pTab->zName);
+ if( opMask & 0x01 ){
+ int r1 = sqlite3GetTempReg(pParse);
+ sqlite3VdbeAddOp4(v, OP_String8, 0, r1, 0, zSubSql, P4_DYNAMIC);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, r1, 1);
+ }else{
+ sqlite3VdbeAddOp4(v, OP_SqlExec, 0, 0, 0, zSubSql, P4_DYNAMIC);
+ }
+ }
+ }
+ sqlite3VdbeAddOp0(v, OP_Expire);
+ break;
+ }
+
/*
** PRAGMA busy_timeout
** PRAGMA busy_timeout = N
@@ -113403,7 +117338,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
if( zRight ){
sqlite3_busy_timeout(db, sqlite3Atoi(zRight));
}
- returnSingleInt(v, "timeout", db->busyTimeout);
+ returnSingleInt(v, db->busyTimeout);
break;
}
@@ -113423,7 +117358,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
if( zRight && sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK ){
sqlite3_soft_heap_limit64(N);
}
- returnSingleInt(v, "soft_heap_limit", sqlite3_soft_heap_limit64(-1));
+ returnSingleInt(v, sqlite3_soft_heap_limit64(-1));
break;
}
@@ -113442,8 +117377,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
){
sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, (int)(N&0x7fffffff));
}
- returnSingleInt(v, "threads",
- sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, -1));
+ returnSingleInt(v, sqlite3_limit(db, SQLITE_LIMIT_WORKER_THREADS, -1));
break;
}
@@ -113455,9 +117389,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
static const char *const azLockName[] = {
"unlocked", "shared", "reserved", "pending", "exclusive"
};
- static const char *azCol[] = { "database", "status" };
int i;
- setAllColumnNames(v, 2, azCol); assert( 2==ArraySize(azCol) );
pParse->nMem = 2;
for(i=0; inDb; i++){
Btree *pBt;
@@ -113472,7 +117404,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
zState = azLockName[j];
}
sqlite3VdbeMultiLoad(v, 1, "ss", db->aDb[i].zDbSName, zState);
- sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2);
}
break;
}
@@ -113523,10 +117454,329 @@ SQLITE_PRIVATE void sqlite3Pragma(
} /* End of the PRAGMA switch */
+ /* The following block is a no-op unless SQLITE_DEBUG is defined. Its only
+ ** purpose is to execute assert() statements to verify that if the
+ ** PragFlg_NoColumns1 flag is set and the caller specified an argument
+ ** to the PRAGMA, the implementation has not added any OP_ResultRow
+ ** instructions to the VM. */
+ if( (pPragma->mPragFlg & PragFlg_NoColumns1) && zRight ){
+ sqlite3VdbeVerifyNoResultRow(v);
+ }
+
pragma_out:
sqlite3DbFree(db, zLeft);
sqlite3DbFree(db, zRight);
}
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/*****************************************************************************
+** Implementation of an eponymous virtual table that runs a pragma.
+**
+*/
+typedef struct PragmaVtab PragmaVtab;
+typedef struct PragmaVtabCursor PragmaVtabCursor;
+struct PragmaVtab {
+ sqlite3_vtab base; /* Base class. Must be first */
+ sqlite3 *db; /* The database connection to which it belongs */
+ const PragmaName *pName; /* Name of the pragma */
+ u8 nHidden; /* Number of hidden columns */
+ u8 iHidden; /* Index of the first hidden column */
+};
+struct PragmaVtabCursor {
+ sqlite3_vtab_cursor base; /* Base class. Must be first */
+ sqlite3_stmt *pPragma; /* The pragma statement to run */
+ sqlite_int64 iRowid; /* Current rowid */
+ char *azArg[2]; /* Value of the argument and schema */
+};
+
+/*
+** Pragma virtual table module xConnect method.
+*/
+static int pragmaVtabConnect(
+ sqlite3 *db,
+ void *pAux,
+ int argc, const char *const*argv,
+ sqlite3_vtab **ppVtab,
+ char **pzErr
+){
+ const PragmaName *pPragma = (const PragmaName*)pAux;
+ PragmaVtab *pTab = 0;
+ int rc;
+ int i, j;
+ char cSep = '(';
+ StrAccum acc;
+ char zBuf[200];
+
+ UNUSED_PARAMETER(argc);
+ UNUSED_PARAMETER(argv);
+ sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
+ sqlite3StrAccumAppendAll(&acc, "CREATE TABLE x");
+ for(i=0, j=pPragma->iPragCName; inPragCName; i++, j++){
+ sqlite3XPrintf(&acc, "%c\"%s\"", cSep, pragCName[j]);
+ cSep = ',';
+ }
+ if( i==0 ){
+ sqlite3XPrintf(&acc, "(\"%s\"", pPragma->zName);
+ cSep = ',';
+ i++;
+ }
+ j = 0;
+ if( pPragma->mPragFlg & PragFlg_Result1 ){
+ sqlite3StrAccumAppendAll(&acc, ",arg HIDDEN");
+ j++;
+ }
+ if( pPragma->mPragFlg & (PragFlg_SchemaOpt|PragFlg_SchemaReq) ){
+ sqlite3StrAccumAppendAll(&acc, ",schema HIDDEN");
+ j++;
+ }
+ sqlite3StrAccumAppend(&acc, ")", 1);
+ sqlite3StrAccumFinish(&acc);
+ assert( strlen(zBuf) < sizeof(zBuf)-1 );
+ rc = sqlite3_declare_vtab(db, zBuf);
+ if( rc==SQLITE_OK ){
+ pTab = (PragmaVtab*)sqlite3_malloc(sizeof(PragmaVtab));
+ if( pTab==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ memset(pTab, 0, sizeof(PragmaVtab));
+ pTab->pName = pPragma;
+ pTab->db = db;
+ pTab->iHidden = i;
+ pTab->nHidden = j;
+ }
+ }else{
+ *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
+ }
+
+ *ppVtab = (sqlite3_vtab*)pTab;
+ return rc;
+}
+
+/*
+** Pragma virtual table module xDisconnect method.
+*/
+static int pragmaVtabDisconnect(sqlite3_vtab *pVtab){
+ PragmaVtab *pTab = (PragmaVtab*)pVtab;
+ sqlite3_free(pTab);
+ return SQLITE_OK;
+}
+
+/* Figure out the best index to use to search a pragma virtual table.
+**
+** There are not really any index choices. But we want to encourage the
+** query planner to give == constraints on as many hidden parameters as
+** possible, and especially on the first hidden parameter. So return a
+** high cost if hidden parameters are unconstrained.
+*/
+static int pragmaVtabBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
+ PragmaVtab *pTab = (PragmaVtab*)tab;
+ const struct sqlite3_index_constraint *pConstraint;
+ int i, j;
+ int seen[2];
+
+ pIdxInfo->estimatedCost = (double)1;
+ if( pTab->nHidden==0 ){ return SQLITE_OK; }
+ pConstraint = pIdxInfo->aConstraint;
+ seen[0] = 0;
+ seen[1] = 0;
+ for(i=0; inConstraint; i++, pConstraint++){
+ if( pConstraint->usable==0 ) continue;
+ if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
+ if( pConstraint->iColumn < pTab->iHidden ) continue;
+ j = pConstraint->iColumn - pTab->iHidden;
+ assert( j < 2 );
+ seen[j] = i+1;
+ }
+ if( seen[0]==0 ){
+ pIdxInfo->estimatedCost = (double)2147483647;
+ pIdxInfo->estimatedRows = 2147483647;
+ return SQLITE_OK;
+ }
+ j = seen[0]-1;
+ pIdxInfo->aConstraintUsage[j].argvIndex = 1;
+ pIdxInfo->aConstraintUsage[j].omit = 1;
+ if( seen[1]==0 ) return SQLITE_OK;
+ pIdxInfo->estimatedCost = (double)20;
+ pIdxInfo->estimatedRows = 20;
+ j = seen[1]-1;
+ pIdxInfo->aConstraintUsage[j].argvIndex = 2;
+ pIdxInfo->aConstraintUsage[j].omit = 1;
+ return SQLITE_OK;
+}
+
+/* Create a new cursor for the pragma virtual table */
+static int pragmaVtabOpen(sqlite3_vtab *pVtab, sqlite3_vtab_cursor **ppCursor){
+ PragmaVtabCursor *pCsr;
+ pCsr = (PragmaVtabCursor*)sqlite3_malloc(sizeof(*pCsr));
+ if( pCsr==0 ) return SQLITE_NOMEM;
+ memset(pCsr, 0, sizeof(PragmaVtabCursor));
+ pCsr->base.pVtab = pVtab;
+ *ppCursor = &pCsr->base;
+ return SQLITE_OK;
+}
+
+/* Clear all content from pragma virtual table cursor. */
+static void pragmaVtabCursorClear(PragmaVtabCursor *pCsr){
+ int i;
+ sqlite3_finalize(pCsr->pPragma);
+ pCsr->pPragma = 0;
+ for(i=0; iazArg); i++){
+ sqlite3_free(pCsr->azArg[i]);
+ pCsr->azArg[i] = 0;
+ }
+}
+
+/* Close a pragma virtual table cursor */
+static int pragmaVtabClose(sqlite3_vtab_cursor *cur){
+ PragmaVtabCursor *pCsr = (PragmaVtabCursor*)cur;
+ pragmaVtabCursorClear(pCsr);
+ sqlite3_free(pCsr);
+ return SQLITE_OK;
+}
+
+/* Advance the pragma virtual table cursor to the next row */
+static int pragmaVtabNext(sqlite3_vtab_cursor *pVtabCursor){
+ PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor;
+ int rc = SQLITE_OK;
+
+ /* Increment the xRowid value */
+ pCsr->iRowid++;
+ assert( pCsr->pPragma );
+ if( SQLITE_ROW!=sqlite3_step(pCsr->pPragma) ){
+ rc = sqlite3_finalize(pCsr->pPragma);
+ pCsr->pPragma = 0;
+ pragmaVtabCursorClear(pCsr);
+ }
+ return rc;
+}
+
+/*
+** Pragma virtual table module xFilter method.
+*/
+static int pragmaVtabFilter(
+ sqlite3_vtab_cursor *pVtabCursor,
+ int idxNum, const char *idxStr,
+ int argc, sqlite3_value **argv
+){
+ PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor;
+ PragmaVtab *pTab = (PragmaVtab*)(pVtabCursor->pVtab);
+ int rc;
+ int i, j;
+ StrAccum acc;
+ char *zSql;
+
+ UNUSED_PARAMETER(idxNum);
+ UNUSED_PARAMETER(idxStr);
+ pragmaVtabCursorClear(pCsr);
+ j = (pTab->pName->mPragFlg & PragFlg_Result1)!=0 ? 0 : 1;
+ for(i=0; iazArg) );
+ assert( pCsr->azArg[j]==0 );
+ if( zText ){
+ pCsr->azArg[j] = sqlite3_mprintf("%s", zText);
+ if( pCsr->azArg[j]==0 ){
+ return SQLITE_NOMEM;
+ }
+ }
+ }
+ sqlite3StrAccumInit(&acc, 0, 0, 0, pTab->db->aLimit[SQLITE_LIMIT_SQL_LENGTH]);
+ sqlite3StrAccumAppendAll(&acc, "PRAGMA ");
+ if( pCsr->azArg[1] ){
+ sqlite3XPrintf(&acc, "%Q.", pCsr->azArg[1]);
+ }
+ sqlite3StrAccumAppendAll(&acc, pTab->pName->zName);
+ if( pCsr->azArg[0] ){
+ sqlite3XPrintf(&acc, "=%Q", pCsr->azArg[0]);
+ }
+ zSql = sqlite3StrAccumFinish(&acc);
+ if( zSql==0 ) return SQLITE_NOMEM;
+ rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pCsr->pPragma, 0);
+ sqlite3_free(zSql);
+ if( rc!=SQLITE_OK ){
+ pTab->base.zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pTab->db));
+ return rc;
+ }
+ return pragmaVtabNext(pVtabCursor);
+}
+
+/*
+** Pragma virtual table module xEof method.
+*/
+static int pragmaVtabEof(sqlite3_vtab_cursor *pVtabCursor){
+ PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor;
+ return (pCsr->pPragma==0);
+}
+
+/* The xColumn method simply returns the corresponding column from
+** the PRAGMA.
+*/
+static int pragmaVtabColumn(
+ sqlite3_vtab_cursor *pVtabCursor,
+ sqlite3_context *ctx,
+ int i
+){
+ PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor;
+ PragmaVtab *pTab = (PragmaVtab*)(pVtabCursor->pVtab);
+ if( iiHidden ){
+ sqlite3_result_value(ctx, sqlite3_column_value(pCsr->pPragma, i));
+ }else{
+ sqlite3_result_text(ctx, pCsr->azArg[i-pTab->iHidden],-1,SQLITE_TRANSIENT);
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Pragma virtual table module xRowid method.
+*/
+static int pragmaVtabRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *p){
+ PragmaVtabCursor *pCsr = (PragmaVtabCursor*)pVtabCursor;
+ *p = pCsr->iRowid;
+ return SQLITE_OK;
+}
+
+/* The pragma virtual table object */
+static const sqlite3_module pragmaVtabModule = {
+ 0, /* iVersion */
+ 0, /* xCreate - create a table */
+ pragmaVtabConnect, /* xConnect - connect to an existing table */
+ pragmaVtabBestIndex, /* xBestIndex - Determine search strategy */
+ pragmaVtabDisconnect, /* xDisconnect - Disconnect from a table */
+ 0, /* xDestroy - Drop a table */
+ pragmaVtabOpen, /* xOpen - open a cursor */
+ pragmaVtabClose, /* xClose - close a cursor */
+ pragmaVtabFilter, /* xFilter - configure scan constraints */
+ pragmaVtabNext, /* xNext - advance a cursor */
+ pragmaVtabEof, /* xEof */
+ pragmaVtabColumn, /* xColumn - read data */
+ pragmaVtabRowid, /* xRowid - read data */
+ 0, /* xUpdate - write data */
+ 0, /* xBegin - begin transaction */
+ 0, /* xSync - sync transaction */
+ 0, /* xCommit - commit transaction */
+ 0, /* xRollback - rollback transaction */
+ 0, /* xFindFunction - function overloading */
+ 0, /* xRename - rename the table */
+ 0, /* xSavepoint */
+ 0, /* xRelease */
+ 0 /* xRollbackTo */
+};
+
+/*
+** Check to see if zTabName is really the name of a pragma. If it is,
+** then register an eponymous virtual table for that pragma and return
+** a pointer to the Module object for the new virtual table.
+*/
+SQLITE_PRIVATE Module *sqlite3PragmaVtabRegister(sqlite3 *db, const char *zName){
+ const PragmaName *pName;
+ assert( sqlite3_strnicmp(zName, "pragma_", 7)==0 );
+ pName = pragmaLocate(zName+7);
+ if( pName==0 ) return 0;
+ if( (pName->mPragFlg & (PragFlg_Result0|PragFlg_Result1))==0 ) return 0;
+ assert( sqlite3HashFind(&db->aModule, zName)==0 );
+ return sqlite3VtabCreateModule(db, zName, &pragmaVtabModule, (void*)pName, 0);
+}
+
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
#endif /* SQLITE_OMIT_PRAGMA */
@@ -113559,7 +117809,7 @@ static void corruptSchema(
const char *zExtra /* Error information */
){
sqlite3 *db = pData->db;
- if( !db->mallocFailed && (db->flags & SQLITE_RecoveryMode)==0 ){
+ if( !db->mallocFailed && (db->flags & SQLITE_WriteSchema)==0 ){
char *z;
if( zObj==0 ) zObj = "?";
z = sqlite3MPrintf(db, "malformed database schema (%s)", zObj);
@@ -113619,7 +117869,7 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char
rc = db->errCode;
assert( (rc&0xFF)==(rcp&0xFF) );
db->init.iDb = saved_iDb;
- assert( saved_iDb==0 || (db->flags & SQLITE_Vacuum)!=0 );
+ assert( saved_iDb==0 || (db->mDbFlags & DBFLAG_Vacuum)!=0 );
if( SQLITE_OK!=rc ){
if( db->init.orphanTrigger ){
assert( iDb==1 );
@@ -113684,6 +117934,8 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
assert( sqlite3_mutex_held(db->mutex) );
assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );
+ db->init.busy = 1;
+
/* Construct the in-memory representation schema tables (sqlite_master or
** sqlite_temp_master) by invoking the parser directly. The appropriate
** table name will be inserted automatically by the parser so we can just
@@ -113692,7 +117944,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
azArg[0] = zMasterName = SCHEMA_TABLE(iDb);
azArg[1] = "1";
azArg[2] = "CREATE TABLE x(type text,name text,tbl_name text,"
- "rootpage integer,sql text)";
+ "rootpage int,sql text)";
azArg[3] = 0;
initData.db = db;
initData.iDb = iDb;
@@ -113708,10 +117960,10 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
*/
pDb = &db->aDb[iDb];
if( pDb->pBt==0 ){
- if( !OMIT_TEMPDB && ALWAYS(iDb==1) ){
- DbSetProperty(db, 1, DB_SchemaLoaded);
- }
- return SQLITE_OK;
+ assert( iDb==1 );
+ DbSetProperty(db, 1, DB_SchemaLoaded);
+ rc = SQLITE_OK;
+ goto error_out;
}
/* If there is not already a read-only (or read-write) transaction opened
@@ -113846,8 +118098,8 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
rc = SQLITE_NOMEM_BKPT;
sqlite3ResetAllSchemasOfConnection(db);
}
- if( rc==SQLITE_OK || (db->flags&SQLITE_RecoveryMode)){
- /* Black magic: If the SQLITE_RecoveryMode flag is set, then consider
+ if( rc==SQLITE_OK || (db->flags&SQLITE_WriteSchema)){
+ /* Black magic: If the SQLITE_WriteSchema flag is set, then consider
** the schema loaded, even if errors occurred. In this situation the
** current sqlite3_prepare() operation will fail, but the following one
** will attempt to compile the supplied statement against whatever subset
@@ -113870,9 +118122,13 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
sqlite3BtreeLeave(pDb->pBt);
error_out:
- if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
- sqlite3OomFault(db);
+ if( rc ){
+ if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
+ sqlite3OomFault(db);
+ }
+ sqlite3ResetOneSchema(db, iDb);
}
+ db->init.busy = 0;
return rc;
}
@@ -113888,42 +118144,29 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
*/
SQLITE_PRIVATE int sqlite3Init(sqlite3 *db, char **pzErrMsg){
int i, rc;
- int commit_internal = !(db->flags&SQLITE_InternChanges);
+ int commit_internal = !(db->mDbFlags&DBFLAG_SchemaChange);
assert( sqlite3_mutex_held(db->mutex) );
assert( sqlite3BtreeHoldsMutex(db->aDb[0].pBt) );
assert( db->init.busy==0 );
- rc = SQLITE_OK;
- db->init.busy = 1;
ENC(db) = SCHEMA_ENC(db);
- for(i=0; rc==SQLITE_OK && inDb; i++){
- if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue;
- rc = sqlite3InitOne(db, i, pzErrMsg);
- if( rc ){
- sqlite3ResetOneSchema(db, i);
- }
+ assert( db->nDb>0 );
+ /* Do the main schema first */
+ if( !DbHasProperty(db, 0, DB_SchemaLoaded) ){
+ rc = sqlite3InitOne(db, 0, pzErrMsg);
+ if( rc ) return rc;
}
-
- /* Once all the other databases have been initialized, load the schema
- ** for the TEMP database. This is loaded last, as the TEMP database
- ** schema may contain references to objects in other databases.
- */
-#ifndef SQLITE_OMIT_TEMPDB
- assert( db->nDb>1 );
- if( rc==SQLITE_OK && !DbHasProperty(db, 1, DB_SchemaLoaded) ){
- rc = sqlite3InitOne(db, 1, pzErrMsg);
- if( rc ){
- sqlite3ResetOneSchema(db, 1);
+ /* All other schemas after the main schema. The "temp" schema must be last */
+ for(i=db->nDb-1; i>0; i--){
+ if( !DbHasProperty(db, i, DB_SchemaLoaded) ){
+ rc = sqlite3InitOne(db, i, pzErrMsg);
+ if( rc ) return rc;
}
}
-#endif
-
- db->init.busy = 0;
- if( rc==SQLITE_OK && commit_internal ){
+ if( commit_internal ){
sqlite3CommitInternalChanges(db);
}
-
- return rc;
+ return SQLITE_OK;
}
/*
@@ -114014,7 +118257,8 @@ SQLITE_PRIVATE int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){
*/
assert( sqlite3_mutex_held(db->mutex) );
if( pSchema ){
- for(i=0; ALWAYS(inDb); i++){
+ for(i=0; 1; i++){
+ assert( inDb );
if( db->aDb[i].pSchema==pSchema ){
break;
}
@@ -114028,16 +118272,14 @@ SQLITE_PRIVATE int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){
** Free all memory allocations in the pParse object
*/
SQLITE_PRIVATE void sqlite3ParserReset(Parse *pParse){
- if( pParse ){
- sqlite3 *db = pParse->db;
- sqlite3DbFree(db, pParse->aLabel);
- sqlite3ExprListDelete(db, pParse->pConstExpr);
- if( db ){
- assert( db->lookaside.bDisable >= pParse->disableLookaside );
- db->lookaside.bDisable -= pParse->disableLookaside;
- }
- pParse->disableLookaside = 0;
+ sqlite3 *db = pParse->db;
+ sqlite3DbFree(db, pParse->aLabel);
+ sqlite3ExprListDelete(db, pParse->pConstExpr);
+ if( db ){
+ assert( db->lookaside.bDisable >= pParse->disableLookaside );
+ db->lookaside.bDisable -= pParse->disableLookaside;
}
+ pParse->disableLookaside = 0;
}
/*
@@ -114047,7 +118289,7 @@ 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 */
+ u32 prepFlags, /* Zero or more SQLITE_PREPARE_* flags */
Vdbe *pReprepare, /* VM being reprepared */
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
const char **pzTail /* OUT: End of parsed string */
@@ -114064,6 +118306,14 @@ static int sqlite3Prepare(
/* assert( !db->mallocFailed ); // not true with SQLITE_USE_ALLOCA */
assert( sqlite3_mutex_held(db->mutex) );
+ /* For a long-term use prepared statement avoid the use of
+ ** lookaside memory.
+ */
+ if( prepFlags & SQLITE_PREPARE_PERSISTENT ){
+ sParse.disableLookaside++;
+ db->lookaside.bDisable++;
+ }
+
/* Check to verify that it is possible to get a read lock on all
** database schemas. The inability to get a read lock indicates that
** some other database connection is holding a write-lock, which in
@@ -114095,7 +118345,7 @@ static int sqlite3Prepare(
if( rc ){
const char *zDb = db->aDb[i].zDbSName;
sqlite3ErrorWithMsg(db, rc, "database schema is locked: %s", zDb);
- testcase( db->flags & SQLITE_ReadUncommitted );
+ testcase( db->flags & SQLITE_ReadUncommit );
goto end_prepare;
}
}
@@ -114163,8 +118413,7 @@ static int sqlite3Prepare(
#endif
if( db->init.busy==0 ){
- Vdbe *pVdbe = sParse.pVdbe;
- sqlite3VdbeSetSql(pVdbe, zSql, (int)(sParse.zTail-zSql), saveSqlFlag);
+ sqlite3VdbeSetSql(sParse.pVdbe, zSql, (int)(sParse.zTail-zSql), prepFlags);
}
if( sParse.pVdbe && (rc!=SQLITE_OK || db->mallocFailed) ){
sqlite3VdbeFinalize(sParse.pVdbe);
@@ -114190,20 +118439,19 @@ static int sqlite3Prepare(
end_prepare:
sqlite3ParserReset(&sParse);
- rc = sqlite3ApiExit(db, rc);
- assert( (rc&db->errMask)==rc );
return rc;
}
static int sqlite3LockAndPrepare(
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 */
+ u32 prepFlags, /* Zero or more SQLITE_PREPARE_* flags */
Vdbe *pOld, /* VM being reprepared */
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
const char **pzTail /* OUT: End of parsed string */
){
int rc;
+ int cnt = 0;
#ifdef SQLITE_ENABLE_API_ARMOR
if( ppStmt==0 ) return SQLITE_MISUSE_BKPT;
@@ -114214,14 +118462,18 @@ static int sqlite3LockAndPrepare(
}
sqlite3_mutex_enter(db->mutex);
sqlite3BtreeEnterAll(db);
- rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, pOld, ppStmt, pzTail);
- if( rc==SQLITE_SCHEMA ){
- sqlite3_finalize(*ppStmt);
- rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, pOld, ppStmt, pzTail);
- }
+ do{
+ /* Make multiple attempts to compile the SQL, until it either succeeds
+ ** or encounters a permanent error. A schema problem after one schema
+ ** reset is considered a permanent error. */
+ rc = sqlite3Prepare(db, zSql, nBytes, prepFlags, pOld, ppStmt, pzTail);
+ assert( rc==SQLITE_OK || *ppStmt==0 );
+ }while( rc==SQLITE_ERROR_RETRY
+ || (rc==SQLITE_SCHEMA && (sqlite3ResetOneSchema(db,-1), cnt++)==0) );
sqlite3BtreeLeaveAll(db);
+ rc = sqlite3ApiExit(db, rc);
+ assert( (rc&db->errMask)==rc );
sqlite3_mutex_leave(db->mutex);
- assert( rc==SQLITE_OK || *ppStmt==0 );
return rc;
}
@@ -114238,13 +118490,15 @@ SQLITE_PRIVATE int sqlite3Reprepare(Vdbe *p){
sqlite3_stmt *pNew;
const char *zSql;
sqlite3 *db;
+ u8 prepFlags;
assert( sqlite3_mutex_held(sqlite3VdbeDb(p)->mutex) );
zSql = sqlite3_sql((sqlite3_stmt *)p);
assert( zSql!=0 ); /* Reprepare only called for prepare_v2() statements */
db = sqlite3VdbeDb(p);
assert( sqlite3_mutex_held(db->mutex) );
- rc = sqlite3LockAndPrepare(db, zSql, -1, 0, p, &pNew, 0);
+ prepFlags = sqlite3VdbePrepareFlags(p);
+ rc = sqlite3LockAndPrepare(db, zSql, -1, prepFlags, p, &pNew, 0);
if( rc ){
if( rc==SQLITE_NOMEM ){
sqlite3OomFault(db);
@@ -114290,8 +118544,36 @@ SQLITE_API int sqlite3_prepare_v2(
const char **pzTail /* OUT: End of parsed string */
){
int rc;
- rc = sqlite3LockAndPrepare(db,zSql,nBytes,1,0,ppStmt,pzTail);
- assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */
+ /* EVIDENCE-OF: R-37923-12173 The sqlite3_prepare_v2() interface works
+ ** exactly the same as sqlite3_prepare_v3() with a zero prepFlags
+ ** parameter.
+ **
+ ** Proof in that the 5th parameter to sqlite3LockAndPrepare is 0 */
+ rc = sqlite3LockAndPrepare(db,zSql,nBytes,SQLITE_PREPARE_SAVESQL,0,
+ ppStmt,pzTail);
+ assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 );
+ return rc;
+}
+SQLITE_API int sqlite3_prepare_v3(
+ sqlite3 *db, /* Database handle. */
+ const char *zSql, /* UTF-8 encoded SQL statement. */
+ int nBytes, /* Length of zSql in bytes. */
+ unsigned int prepFlags, /* Zero or more SQLITE_PREPARE_* flags */
+ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
+ const char **pzTail /* OUT: End of parsed string */
+){
+ int rc;
+ /* EVIDENCE-OF: R-56861-42673 sqlite3_prepare_v3() differs from
+ ** sqlite3_prepare_v2() only in having the extra prepFlags parameter,
+ ** which is a bit array consisting of zero or more of the
+ ** SQLITE_PREPARE_* flags.
+ **
+ ** Proof by comparison to the implementation of sqlite3_prepare_v2()
+ ** directly above. */
+ rc = sqlite3LockAndPrepare(db,zSql,nBytes,
+ SQLITE_PREPARE_SAVESQL|(prepFlags&SQLITE_PREPARE_MASK),
+ 0,ppStmt,pzTail);
+ assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 );
return rc;
}
@@ -114304,7 +118586,7 @@ static int sqlite3Prepare16(
sqlite3 *db, /* Database handle. */
const void *zSql, /* UTF-16 encoded SQL statement. */
int nBytes, /* Length of zSql in bytes. */
- int saveSqlFlag, /* True to save SQL text into the sqlite3_stmt */
+ u32 prepFlags, /* Zero or more SQLITE_PREPARE_* flags */
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
const void **pzTail /* OUT: End of parsed string */
){
@@ -114332,7 +118614,7 @@ static int sqlite3Prepare16(
sqlite3_mutex_enter(db->mutex);
zSql8 = sqlite3Utf16to8(db, zSql, nBytes, SQLITE_UTF16NATIVE);
if( zSql8 ){
- rc = sqlite3LockAndPrepare(db, zSql8, -1, saveSqlFlag, 0, ppStmt, &zTail8);
+ rc = sqlite3LockAndPrepare(db, zSql8, -1, prepFlags, 0, ppStmt, &zTail8);
}
if( zTail8 && pzTail ){
@@ -114378,7 +118660,22 @@ SQLITE_API int sqlite3_prepare16_v2(
const void **pzTail /* OUT: End of parsed string */
){
int rc;
- rc = sqlite3Prepare16(db,zSql,nBytes,1,ppStmt,pzTail);
+ rc = sqlite3Prepare16(db,zSql,nBytes,SQLITE_PREPARE_SAVESQL,ppStmt,pzTail);
+ assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */
+ return rc;
+}
+SQLITE_API int sqlite3_prepare16_v3(
+ sqlite3 *db, /* Database handle. */
+ const void *zSql, /* UTF-16 encoded SQL statement. */
+ int nBytes, /* Length of zSql in bytes. */
+ unsigned int prepFlags, /* Zero or more SQLITE_PREPARE_* flags */
+ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
+ const void **pzTail /* OUT: End of parsed string */
+){
+ int rc;
+ rc = sqlite3Prepare16(db,zSql,nBytes,
+ SQLITE_PREPARE_SAVESQL|(prepFlags&SQLITE_PREPARE_MASK),
+ ppStmt,pzTail);
assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */
return rc;
}
@@ -114463,9 +118760,8 @@ static void clearSelect(sqlite3 *db, Select *p, int bFree){
sqlite3ExprDelete(db, p->pHaving);
sqlite3ExprListDelete(db, p->pOrderBy);
sqlite3ExprDelete(db, p->pLimit);
- sqlite3ExprDelete(db, p->pOffset);
- if( p->pWith ) sqlite3WithDelete(db, p->pWith);
- if( bFree ) sqlite3DbFree(db, p);
+ if( OK_IF_ALWAYS_TRUE(p->pWith) ) sqlite3WithDelete(db, p->pWith);
+ if( bFree ) sqlite3DbFreeNN(db, p);
p = pPrior;
bFree = 1;
}
@@ -114496,19 +118792,18 @@ SQLITE_PRIVATE Select *sqlite3SelectNew(
Expr *pHaving, /* the HAVING clause */
ExprList *pOrderBy, /* the ORDER BY clause */
u32 selFlags, /* Flag parameters, such as SF_Distinct */
- Expr *pLimit, /* LIMIT value. NULL means not used */
- Expr *pOffset /* OFFSET value. NULL means no offset */
+ Expr *pLimit /* LIMIT value. NULL means not used */
){
Select *pNew;
Select standin;
- sqlite3 *db = pParse->db;
- pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew) );
+ pNew = sqlite3DbMallocRawNN(pParse->db, sizeof(*pNew) );
if( pNew==0 ){
- assert( db->mallocFailed );
+ assert( pParse->db->mallocFailed );
pNew = &standin;
}
if( pEList==0 ){
- pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db,TK_ASTERISK,0));
+ pEList = sqlite3ExprListAppend(pParse, 0,
+ sqlite3Expr(pParse->db,TK_ASTERISK,0));
}
pNew->pEList = pEList;
pNew->op = TK_SELECT;
@@ -114521,7 +118816,7 @@ SQLITE_PRIVATE Select *sqlite3SelectNew(
pNew->addrOpenEphm[0] = -1;
pNew->addrOpenEphm[1] = -1;
pNew->nSelectRow = 0;
- if( pSrc==0 ) pSrc = sqlite3DbMallocZero(db, sizeof(*pSrc));
+ if( pSrc==0 ) pSrc = sqlite3DbMallocZero(pParse->db, sizeof(*pSrc));
pNew->pSrc = pSrc;
pNew->pWhere = pWhere;
pNew->pGroupBy = pGroupBy;
@@ -114530,11 +118825,9 @@ SQLITE_PRIVATE Select *sqlite3SelectNew(
pNew->pPrior = 0;
pNew->pNext = 0;
pNew->pLimit = pLimit;
- pNew->pOffset = pOffset;
pNew->pWith = 0;
- assert( pOffset==0 || pLimit!=0 || pParse->nErr>0 || db->mallocFailed!=0 );
- if( db->mallocFailed ) {
- clearSelect(db, pNew, pNew!=&standin);
+ if( pParse->db->mallocFailed ) {
+ clearSelect(pParse->db, pNew, pNew!=&standin);
pNew = 0;
}else{
assert( pNew->pSrc!=0 || pParse->nErr>0 );
@@ -114559,7 +118852,7 @@ SQLITE_PRIVATE void sqlite3SelectSetName(Select *p, const char *zName){
** Delete the given Select structure and all of its substructures.
*/
SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3 *db, Select *p){
- if( p ) clearSelect(db, p, 1);
+ if( OK_IF_ALWAYS_TRUE(p) ) clearSelect(db, p, 1);
}
/*
@@ -114723,7 +119016,7 @@ static void addWhereTerm(
pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iColLeft);
pE2 = sqlite3CreateColumnExpr(db, pSrc, iRight, iColRight);
- pEq = sqlite3PExpr(pParse, TK_EQ, pE1, pE2, 0);
+ pEq = sqlite3PExpr(pParse, TK_EQ, pE1, pE2);
if( pEq && isOuterJoin ){
ExprSetProperty(pEq, EP_FromJoin);
assert( !ExprHasProperty(pEq, EP_TokenOnly|EP_Reduced) );
@@ -114800,11 +119093,10 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
pLeft = &pSrc->a[0];
pRight = &pLeft[1];
for(i=0; inSrc-1; i++, pRight++, pLeft++){
- Table *pLeftTab = pLeft->pTab;
Table *pRightTab = pRight->pTab;
int isOuter;
- if( NEVER(pLeftTab==0 || pRightTab==0) ) continue;
+ if( NEVER(pLeft->pTab==0 || pRightTab==0) ) continue;
isOuter = (pRight->fg.jointype & JT_OUTER)!=0;
/* When the NATURAL keyword is present, add WHERE clause terms for
@@ -114910,7 +119202,7 @@ static void pushOntoSorter(
int iLimit; /* LIMIT counter */
assert( bSeq==0 || bSeq==1 );
- assert( nData==1 || regData==regOrigData );
+ assert( nData==1 || regData==regOrigData || regOrigData==0 );
if( nPrefixReg ){
assert( nPrefixReg==nExpr+bSeq );
regBase = regData - nExpr - bSeq;
@@ -114922,11 +119214,11 @@ static void pushOntoSorter(
iLimit = pSelect->iOffset ? pSelect->iOffset+1 : pSelect->iLimit;
pSort->labelDone = sqlite3VdbeMakeLabel(v);
sqlite3ExprCodeExprList(pParse, pSort->pOrderBy, regBase, regOrigData,
- SQLITE_ECEL_DUP|SQLITE_ECEL_REF);
+ SQLITE_ECEL_DUP | (regOrigData? SQLITE_ECEL_REF : 0));
if( bSeq ){
sqlite3VdbeAddOp2(v, OP_Sequence, pSort->iECursor, regBase+nExpr);
}
- if( nPrefixReg==0 ){
+ if( nPrefixReg==0 && nData>0 ){
sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+bSeq, nData);
}
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nBase-nOBSat, regRecord);
@@ -114952,11 +119244,11 @@ static void pushOntoSorter(
if( pParse->db->mallocFailed ) return;
pOp->p2 = nKey + nData;
pKI = pOp->p4.pKeyInfo;
- memset(pKI->aSortOrder, 0, pKI->nField); /* Makes OP_Jump below testable */
+ memset(pKI->aSortOrder, 0, pKI->nKeyField); /* Makes OP_Jump testable */
sqlite3VdbeChangeP4(v, -1, (char*)pKI, P4_KEYINFO);
- testcase( pKI->nXField>2 );
+ testcase( pKI->nAllField > pKI->nKeyField+2 );
pOp->p4.pKeyInfo = keyInfoFromExprList(pParse, pSort->pOrderBy, nOBSat,
- pKI->nXField-1);
+ pKI->nAllField-pKI->nKeyField-1);
addrJmp = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp3(v, OP_Jump, addrJmp+1, 0, addrJmp+1); VdbeCoverage(v);
pSort->labelBkOut = sqlite3VdbeMakeLabel(v);
@@ -114976,7 +119268,8 @@ static void pushOntoSorter(
}else{
op = OP_IdxInsert;
}
- sqlite3VdbeAddOp2(v, op, pSort->iECursor, regRecord);
+ sqlite3VdbeAddOp4Int(v, op, pSort->iECursor, regRecord,
+ regBase+nOBSat, nBase-nOBSat);
if( iLimit ){
int addr;
int r1 = 0;
@@ -114984,7 +119277,7 @@ static void pushOntoSorter(
** register is initialized with value of LIMIT+OFFSET.) After the sorter
** fills up, delete the least entry in the sorter after each insert.
** Thus we never hold more than the LIMIT+OFFSET rows in memory at once */
- addr = sqlite3VdbeAddOp3(v, OP_IfNotZero, iLimit, 0, 1); VdbeCoverage(v);
+ addr = sqlite3VdbeAddOp1(v, OP_IfNotZero, iLimit); VdbeCoverage(v);
sqlite3VdbeAddOp1(v, OP_Last, pSort->iECursor);
if( pSort->bOrderedInnerLoop ){
r1 = ++pParse->nMem;
@@ -115044,7 +119337,8 @@ static void codeDistinct(
r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, iMem, N); VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1);
- sqlite3VdbeAddOp2(v, OP_IdxInsert, iTab, r1);
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r1, iMem, N);
+ sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
sqlite3ReleaseTempReg(pParse, r1);
}
@@ -115052,16 +119346,15 @@ static void codeDistinct(
** This routine generates the code for the inside of the inner loop
** of a SELECT.
**
-** If srcTab is negative, then the pEList expressions
+** If srcTab is negative, then the p->pEList expressions
** are evaluated in order to get the data for this row. If srcTab is
-** zero or more, then data is pulled from srcTab and pEList is used only
-** to get number columns and the datatype for each column.
+** zero or more, then data is pulled from srcTab and p->pEList is used only
+** to get the number of columns and the collation sequence for each column.
*/
static void selectInnerLoop(
Parse *pParse, /* The parser context */
Select *p, /* The complete select statement being coded */
- ExprList *pEList, /* List of values being extracted */
- int srcTab, /* Pull data from this table */
+ int srcTab, /* Pull data from this table if non-negative */
SortCtx *pSort, /* If not NULL, info on how to process ORDER BY */
DistinctCtx *pDistinct, /* If not NULL, info on how to process DISTINCT */
SelectDest *pDest, /* How to dispose of the results */
@@ -115070,15 +119363,22 @@ static void selectInnerLoop(
){
Vdbe *v = pParse->pVdbe;
int i;
- int hasDistinct; /* True if the DISTINCT keyword is present */
- int regResult; /* Start of memory holding result set */
+ int hasDistinct; /* True if the DISTINCT keyword is present */
int eDest = pDest->eDest; /* How to dispose of results */
int iParm = pDest->iSDParm; /* First argument to disposal method */
int nResultCol; /* Number of result columns */
int nPrefixReg = 0; /* Number of extra registers before regResult */
+ /* Usually, regResult is the first cell in an array of memory cells
+ ** containing the current result row. In this case regOrig is set to the
+ ** same value. However, if the results are being sent to the sorter, the
+ ** values for any expressions that are also part of the sort-key are omitted
+ ** from this array. In this case regOrig is set to zero. */
+ int regResult; /* Start of memory holding current results */
+ int regOrig; /* Start of memory holding full result (or 0) */
+
assert( v );
- assert( pEList!=0 );
+ assert( p->pEList!=0 );
hasDistinct = pDistinct ? pDistinct->eTnctType : WHERE_DISTINCT_NOOP;
if( pSort && pSort->pOrderBy==0 ) pSort = 0;
if( pSort==0 && !hasDistinct ){
@@ -115088,7 +119388,7 @@ static void selectInnerLoop(
/* Pull the requested columns.
*/
- nResultCol = pEList->nExpr;
+ nResultCol = p->pEList->nExpr;
if( pDest->iSdst==0 ){
if( pSort ){
@@ -115107,11 +119407,11 @@ static void selectInnerLoop(
pParse->nMem += nResultCol;
}
pDest->nSdst = nResultCol;
- regResult = pDest->iSdst;
+ regOrig = regResult = pDest->iSdst;
if( srcTab>=0 ){
for(i=0; ia[i].zName));
+ VdbeComment((v, "%s", p->pEList->a[i].zName));
}
}else if( eDest!=SRT_Exists ){
/* If the destination is an EXISTS(...) expression, the actual
@@ -115123,7 +119423,26 @@ static void selectInnerLoop(
}else{
ecelFlags = 0;
}
- sqlite3ExprCodeExprList(pParse, pEList, regResult, 0, ecelFlags);
+ if( pSort && hasDistinct==0 && eDest!=SRT_EphemTab && eDest!=SRT_Table ){
+ /* For each expression in p->pEList that is a copy of an expression in
+ ** the ORDER BY clause (pSort->pOrderBy), set the associated
+ ** iOrderByCol value to one more than the index of the ORDER BY
+ ** expression within the sort-key that pushOntoSorter() will generate.
+ ** This allows the p->pEList field to be omitted from the sorted record,
+ ** saving space and CPU cycles. */
+ ecelFlags |= (SQLITE_ECEL_OMITREF|SQLITE_ECEL_REF);
+ for(i=pSort->nOBSat; ipOrderBy->nExpr; i++){
+ int j;
+ if( (j = pSort->pOrderBy->a[i].u.x.iOrderByCol)>0 ){
+ p->pEList->a[j-1].u.x.iOrderByCol = i+1-pSort->nOBSat;
+ }
+ }
+ regOrig = 0;
+ assert( eDest==SRT_Set || eDest==SRT_Mem
+ || eDest==SRT_Coroutine || eDest==SRT_Output );
+ }
+ nResultCol = sqlite3ExprCodeExprList(pParse,p->pEList,regResult,
+ 0,ecelFlags);
}
/* If the DISTINCT keyword was present on the SELECT statement
@@ -115155,7 +119474,7 @@ static void selectInnerLoop(
iJump = sqlite3VdbeCurrentAddr(v) + nResultCol;
for(i=0; ia[i].pExpr);
+ CollSeq *pColl = sqlite3ExprCollSeq(pParse, p->pEList->a[i].pExpr);
if( izAffSdst)==nResultCol );
sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, nResultCol,
r1, pDest->zAffSdst, nResultCol);
sqlite3ExprCacheAffinityChange(pParse, regResult, nResultCol);
- sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1);
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol);
sqlite3ReleaseTempReg(pParse, r1);
}
break;
@@ -115289,11 +119608,12 @@ static void selectInnerLoop(
** memory cells and break out of the scan loop.
*/
case SRT_Mem: {
- assert( nResultCol==pDest->nSdst );
if( pSort ){
+ assert( nResultCol<=pDest->nSdst );
pushOntoSorter(
- pParse, pSort, p, regResult, regResult, nResultCol, nPrefixReg);
+ pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg);
}else{
+ assert( nResultCol==pDest->nSdst );
assert( regResult==iParm );
/* The LIMIT clause will jump out of the loop for us */
}
@@ -115306,7 +119626,7 @@ static void selectInnerLoop(
testcase( eDest==SRT_Coroutine );
testcase( eDest==SRT_Output );
if( pSort ){
- pushOntoSorter(pParse, pSort, p, regResult, regResult, nResultCol,
+ pushOntoSorter(pParse, pSort, p, regResult, regOrig, nResultCol,
nPrefixReg);
}else if( eDest==SRT_Coroutine ){
sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm);
@@ -115356,7 +119676,7 @@ static void selectInnerLoop(
}
sqlite3VdbeAddOp2(v, OP_Sequence, iParm, r2+nKey);
sqlite3VdbeAddOp3(v, OP_MakeRecord, r2, nKey+2, r1);
- sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1);
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, r2, nKey+2);
if( addrTest ) sqlite3VdbeJumpHere(v, addrTest);
sqlite3ReleaseTempReg(pParse, r1);
sqlite3ReleaseTempRange(pParse, r2, nKey+2);
@@ -115393,12 +119713,12 @@ static void selectInnerLoop(
** X extra columns.
*/
SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){
- int nExtra = (N+X)*(sizeof(CollSeq*)+1);
+ int nExtra = (N+X)*(sizeof(CollSeq*)+1) - sizeof(CollSeq*);
KeyInfo *p = sqlite3DbMallocRawNN(db, sizeof(KeyInfo) + nExtra);
if( p ){
p->aSortOrder = (u8*)&p->aColl[N+X];
- p->nField = (u16)N;
- p->nXField = (u16)X;
+ p->nKeyField = (u16)N;
+ p->nAllField = (u16)(N+X);
p->enc = ENC(db);
p->db = db;
p->nRef = 1;
@@ -115416,7 +119736,7 @@ SQLITE_PRIVATE void sqlite3KeyInfoUnref(KeyInfo *p){
if( p ){
assert( p->nRef>0 );
p->nRef--;
- if( p->nRef==0 ) sqlite3DbFree(p->db, p);
+ if( p->nRef==0 ) sqlite3DbFreeNN(p->db, p);
}
}
@@ -115472,10 +119792,7 @@ static KeyInfo *keyInfoFromExprList(
if( pInfo ){
assert( sqlite3KeyInfoIsWriteable(pInfo) );
for(i=iStart, pItem=pList->a+iStart; ipExpr);
- if( !pColl ) pColl = db->pDfltColl;
- pInfo->aColl[i-iStart] = pColl;
+ pInfo->aColl[i-iStart] = sqlite3ExprNNCollSeq(pParse, pItem->pExpr);
pInfo->aSortOrder[i-iStart] = pItem->sortOrder;
}
}
@@ -115591,14 +119908,13 @@ static void generateSortTail(
int iParm = pDest->iSDParm;
int regRow;
int regRowid;
+ int iCol;
int nKey;
int iSortTab; /* Sorter cursor to read from */
int nSortData; /* Trailing values to read from sorter */
int i;
int bSeq; /* True if sorter record includes seq. no. */
-#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
struct ExprList_item *aOutEx = p->pEList->a;
-#endif
assert( addrBreak<0 );
if( pSort->labelBkOut ){
@@ -115636,11 +119952,18 @@ static void generateSortTail(
iSortTab = iTab;
bSeq = 1;
}
- for(i=0; izAffSdst, nColumn);
sqlite3ExprCacheAffinityChange(pParse, regRow, nColumn);
- sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, regRowid);
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, regRowid, regRow, nColumn);
break;
}
case SRT_Mem: {
@@ -115719,23 +120042,23 @@ static void generateSortTail(
** the SQLITE_ENABLE_COLUMN_METADATA compile-time option is used.
*/
#ifdef SQLITE_ENABLE_COLUMN_METADATA
-# define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,C,D,E,F)
+# define columnType(A,B,C,D,E) columnTypeImpl(A,B,C,D,E)
#else /* if !defined(SQLITE_ENABLE_COLUMN_METADATA) */
-# define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,F)
+# define columnType(A,B,C,D,E) columnTypeImpl(A,B)
#endif
static const char *columnTypeImpl(
NameContext *pNC,
+#ifndef SQLITE_ENABLE_COLUMN_METADATA
+ Expr *pExpr
+#else
Expr *pExpr,
-#ifdef SQLITE_ENABLE_COLUMN_METADATA
const char **pzOrigDb,
const char **pzOrigTab,
- const char **pzOrigCol,
+ const char **pzOrigCol
#endif
- u8 *pEstWidth
){
char const *zType = 0;
int j;
- u8 estWidth = 1;
#ifdef SQLITE_ENABLE_COLUMN_METADATA
char const *zOrigDb = 0;
char const *zOrigTab = 0;
@@ -115744,8 +120067,9 @@ static const char *columnTypeImpl(
assert( pExpr!=0 );
assert( pNC->pSrcList!=0 );
+ assert( pExpr->op!=TK_AGG_COLUMN ); /* This routine runes before aggregates
+ ** are processed */
switch( pExpr->op ){
- case TK_AGG_COLUMN:
case TK_COLUMN: {
/* The expression is a column. Locate the table the column is being
** extracted from in NameContext.pSrcList. This table may be real
@@ -115754,8 +120078,6 @@ static const char *columnTypeImpl(
Table *pTab = 0; /* Table structure column is extracted from */
Select *pS = 0; /* Select the column is extracted from */
int iCol = pExpr->iColumn; /* Index of column in pTab */
- testcase( pExpr->op==TK_AGG_COLUMN );
- testcase( pExpr->op==TK_COLUMN );
while( pNC && !pTab ){
SrcList *pTabList = pNC->pSrcList;
for(j=0;jnSrc && pTabList->a[j].iCursor!=pExpr->iTable;j++);
@@ -115794,46 +120116,42 @@ static const char *columnTypeImpl(
** of the SELECT statement. Return the declaration type and origin
** data for the result-set column of the sub-select.
*/
- if( iCol>=0 && ALWAYS(iColpEList->nExpr) ){
+ if( iCol>=0 && iColpEList->nExpr ){
/* If iCol is less than zero, then the expression requests the
** rowid of the sub-select or view. This expression is legal (see
** test case misc2.2.2) - it always evaluates to NULL.
- **
- ** The ALWAYS() is because iCol>=pS->pEList->nExpr will have been
- ** caught already by name resolution.
*/
NameContext sNC;
Expr *p = pS->pEList->a[iCol].pExpr;
sNC.pSrcList = pS->pSrc;
sNC.pNext = pNC;
sNC.pParse = pNC->pParse;
- zType = columnType(&sNC, p,&zOrigDb,&zOrigTab,&zOrigCol, &estWidth);
+ zType = columnType(&sNC, p,&zOrigDb,&zOrigTab,&zOrigCol);
}
- }else if( pTab->pSchema ){
- /* A real table */
+ }else{
+ /* A real table or a CTE table */
assert( !pS );
- if( iCol<0 ) iCol = pTab->iPKey;
- assert( iCol==-1 || (iCol>=0 && iColnCol) );
#ifdef SQLITE_ENABLE_COLUMN_METADATA
+ if( iCol<0 ) iCol = pTab->iPKey;
+ assert( iCol==XN_ROWID || (iCol>=0 && iColnCol) );
if( iCol<0 ){
zType = "INTEGER";
zOrigCol = "rowid";
}else{
zOrigCol = pTab->aCol[iCol].zName;
zType = sqlite3ColumnType(&pTab->aCol[iCol],0);
- estWidth = pTab->aCol[iCol].szEst;
}
zOrigTab = pTab->zName;
- if( pNC->pParse ){
+ if( pNC->pParse && pTab->pSchema ){
int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema);
zOrigDb = pNC->pParse->db->aDb[iDb].zDbSName;
}
#else
+ assert( iCol==XN_ROWID || (iCol>=0 && iColnCol) );
if( iCol<0 ){
zType = "INTEGER";
}else{
zType = sqlite3ColumnType(&pTab->aCol[iCol],0);
- estWidth = pTab->aCol[iCol].szEst;
}
#endif
}
@@ -115852,7 +120170,7 @@ static const char *columnTypeImpl(
sNC.pSrcList = pS->pSrc;
sNC.pNext = pNC;
sNC.pParse = pNC->pParse;
- zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol, &estWidth);
+ zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol);
break;
}
#endif
@@ -115866,7 +120184,6 @@ static const char *columnTypeImpl(
*pzOrigCol = zOrigCol;
}
#endif
- if( pEstWidth ) *pEstWidth = estWidth;
return zType;
}
@@ -115885,6 +120202,7 @@ static void generateColumnTypes(
NameContext sNC;
sNC.pSrcList = pTabList;
sNC.pParse = pParse;
+ sNC.pNext = 0;
for(i=0; inExpr; i++){
Expr *p = pEList->a[i].pExpr;
const char *zType;
@@ -115892,7 +120210,7 @@ static void generateColumnTypes(
const char *zOrigDb = 0;
const char *zOrigTab = 0;
const char *zOrigCol = 0;
- zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol, 0);
+ 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
@@ -115902,27 +120220,56 @@ static void generateColumnTypes(
sqlite3VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, SQLITE_TRANSIENT);
sqlite3VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, SQLITE_TRANSIENT);
#else
- zType = columnType(&sNC, p, 0, 0, 0, 0);
+ zType = columnType(&sNC, p, 0, 0, 0);
#endif
sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, SQLITE_TRANSIENT);
}
#endif /* !defined(SQLITE_OMIT_DECLTYPE) */
}
+
/*
-** Generate code that will tell the VDBE the names of columns
-** in the result set. This information is used to provide the
-** azCol[] values in the callback.
+** Compute the column names for a SELECT statement.
+**
+** The only guarantee that SQLite makes about column names is that if the
+** column has an AS clause assigning it a name, that will be the name used.
+** That is the only documented guarantee. However, countless applications
+** developed over the years have made baseless assumptions about column names
+** and will break if those assumptions changes. Hence, use extreme caution
+** when modifying this routine to avoid breaking legacy.
+**
+** See Also: sqlite3ColumnsFromExprList()
+**
+** The PRAGMA short_column_names and PRAGMA full_column_names settings are
+** deprecated. The default setting is short=ON, full=OFF. 99.9% of all
+** applications should operate this way. Nevertheless, we need to support the
+** other modes for legacy:
+**
+** short=OFF, full=OFF: Column name is the text of the expression has it
+** originally appears in the SELECT statement. In
+** other words, the zSpan of the result expression.
+**
+** short=ON, full=OFF: (This is the default setting). If the result
+** refers directly to a table column, then the
+** result column name is just the table column
+** name: COLUMN. Otherwise use zSpan.
+**
+** full=ON, short=ANY: If the result refers directly to a table column,
+** then the result column name with the table name
+** prefix, ex: TABLE.COLUMN. Otherwise use zSpan.
*/
static void generateColumnNames(
Parse *pParse, /* Parser context */
- SrcList *pTabList, /* List of tables */
- ExprList *pEList /* Expressions defining the result set */
+ Select *pSelect /* Generate column names for this SELECT statement */
){
Vdbe *v = pParse->pVdbe;
- int i, j;
+ int i;
+ Table *pTab;
+ SrcList *pTabList;
+ ExprList *pEList;
sqlite3 *db = pParse->db;
- int fullNames, shortNames;
+ int fullName; /* TABLE.COLUMN if no AS clause and is a direct table ref */
+ int srcName; /* COLUMN or TABLE.COLUMN if no AS clause and is direct */
#ifndef SQLITE_OMIT_EXPLAIN
/* If this is an EXPLAIN, skip this step */
@@ -115932,28 +120279,32 @@ static void generateColumnNames(
#endif
if( pParse->colNamesSet || db->mallocFailed ) return;
+ /* Column names are determined by the left-most term of a compound select */
+ while( pSelect->pPrior ) pSelect = pSelect->pPrior;
+ SELECTTRACE(1,pParse,pSelect,("generating column names\n"));
+ pTabList = pSelect->pSrc;
+ pEList = pSelect->pEList;
assert( v!=0 );
assert( pTabList!=0 );
pParse->colNamesSet = 1;
- fullNames = (db->flags & SQLITE_FullColNames)!=0;
- shortNames = (db->flags & SQLITE_ShortColNames)!=0;
+ fullName = (db->flags & SQLITE_FullColNames)!=0;
+ srcName = (db->flags & SQLITE_ShortColNames)!=0 || fullName;
sqlite3VdbeSetNumCols(v, pEList->nExpr);
for(i=0; inExpr; i++){
- Expr *p;
- p = pEList->a[i].pExpr;
- if( NEVER(p==0) ) continue;
+ Expr *p = pEList->a[i].pExpr;
+
+ assert( p!=0 );
+ assert( p->op!=TK_AGG_COLUMN ); /* Agg processing has not run yet */
+ assert( p->op!=TK_COLUMN || p->pTab!=0 ); /* Covering idx not yet coded */
if( pEList->a[i].zName ){
+ /* An AS clause always takes first priority */
char *zName = pEList->a[i].zName;
sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_TRANSIENT);
- }else if( p->op==TK_COLUMN || p->op==TK_AGG_COLUMN ){
- Table *pTab;
+ }else if( srcName && p->op==TK_COLUMN ){
char *zCol;
int iCol = p->iColumn;
- for(j=0; ALWAYS(j